CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

PWM controlled through I2C BH1750

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
stratogama



Joined: 03 Sep 2015
Posts: 2

View user's profile Send private message Send e-mail

PWM controlled through I2C BH1750
PostPosted: Fri Dec 11, 2015 1:17 pm     Reply with quote

Hello everyone, I'm trying to drive my lights through BH1750 module.
This device uses I2C to communicate with microcontrollers. The idea is to exploit to the maximum ambient light and then the electric light, to do this, first I measure the light of my lamp with the maximum duty cycle to define a preset value, then reduce it to a minimum duty cycle. After all this, I make an infinite loop in which I measure the ambient brightness and compare this value with the preset value and then reduce or increase the duty cycle.

But when I test on the circuit this does not work. Sad

I tested the modules separately and works perfectly, but together only works until the part of the while loop.

I hope you can help me and give me some advice please. Sad

Here my code:
Code:
#include <16f877a.h>
#use delay (clock=20000000)
#fuses HS
#fuses NOWDT
#fuses NOLVP
#fuses NOPROTECT

#use I2C(MASTER, sda=PIN_C4, scl=PIN_C3)
#define PWR_DOWN       0x00
#define PWR_ON         0x01
#define RESET          0X07
#define MODE_HIGH_RES1 0X10
#define MODE_HIGH_RES2 0X11
#define MODE_LOW_RES   0x13
#define ADDR_HIGH_R    0xB9
#define ADDR_HIGH_W    0xB8
#define ADDR_LOW_R     0X47
#define ADDR_LOW_W     0x46


unsigned long MUESTRA,LUX,PWM,PRESET;
char HB,LB;

//funcion para activar y configurar el modulo sensor de luminosidad
void BH1750_init()
{
 I2C_START();
 I2C_WRITE(ADDR_LOW_W);
 I2C_WRITE(PWR_ON);
 I2C_WRITE(RESET);
 I2C_WRITE(ADDR_LOW_W);
 I2C_WRITE(MODE_HIGH_RES1);
 I2C_STOP();
 delay_ms(100);
}


void main()
{
 //configuro canal PWM y BH1750
 setup_ccp1(CCP_PWM);
 setup_timer_2(T2_DIV_BY_4,83,1);
 BH1750_init();
 
 //inicio canal PWM en 0 y luego lo subo al 99% aprox.
 set_pwm1_duty(0L);
 set_pwm1_duty(82L);
 
 //guardo la maxima luminosidad de la luminaria en PRESET
 I2C_START();
 I2C_WRITE(ADDR_LOW_R);
 HB=I2C_READ(1);
 LB=I2C_READ(0);
 I2C_STOP();
 MUESTRA=make16(HB,LB);
 PRESET=(MUESTRA/1.2);
 
 //bajo el valor del PWM a 0, como al inicio
 set_pwm1_duty(0L);
 
 while(1)
 {
  I2C_START();
  I2C_WRITE(ADDR_LOW_R);
  HB=I2C_READ(1);
  LB=I2C_READ(0);
  I2C_STOP();
  MUESTRA=make16(HB,LB);
  LUX=(MUESTRA/1.2);
 
  PWM=0;
 
  if(LUX<PRESET)
  {
   PWM=PWM+1;
   set_pwm1_duty(PWM);
  }
  else if(LUX>PRESET)
  {
   PWM=PWM-1;
   set_pwm1_duty(PWM);
  }
 
 }
}


And my scheme:
http://imageshack.com/a/img911/1525/48xw6Q.png
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Dec 11, 2015 1:47 pm     Reply with quote

Quote:
but together only works until the part of the while loop.

What does this mean ? Give more details on what it is doing when it fails.

Add some printf statements to display the status of your program
while it's running. See the lines in bold below. If you put in these
debug statements, you will be able to see the problems in your code.
Display the printf output in a terminal program such as TeraTerm.
Quote:

#include <16f877a.h>
#fuses HS
#fuses NOWDT
#fuses NOLVP
#fuses NOPROTECT
#use delay (clock=20000000)
#use rs232(9600, UART1, ERRORS)
.
.
.

while(1)
{
I2C_START();
I2C_WRITE(ADDR_LOW_R);
HB=I2C_READ(1);
LB=I2C_READ(0);
I2C_STOP();
MUESTRA=make16(HB,LB);
LUX=(MUESTRA/1.2);

printf("Lux = %lu, Preset = %lu \n\r", LUX, PRESET);

PWM=0;

if(LUX<PRESET)
{
PWM=PWM+1;
printf("Low Lux. New PWM duty = %lu \n\r", PWM);
set_pwm1_duty(PWM);
}
else if(LUX>PRESET)
{
PWM=PWM-1;
printf("High Lux. New PWM duty = %lu \n\r", PWM);
set_pwm1_duty(PWM);
}

printf("\n\r");
delay_ms(500);
}

Also, the preferred style for C is that code (function names, variables, etc.) is in lower case, and constants ( #define VALUES) are in upper case. It makes the source code easier to understand quickly.
temtronic



Joined: 01 Jul 2010
Posts: 9142
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Dec 11, 2015 7:59 pm     Reply with quote

just a note...

PRESET=(MUESTRA/1.2);

You've defined both variables as unsigned long yet do a floating point divide..

I'm thinking that the compiler WILL do a FP divide then cast back into 16 bit int for you...but...better check....

also FP math is very time consuming ! Better to use 'scaled integers' or similar integer math, could easily be 5-10X faster asn just as accurate...

Jay
stratogama



Joined: 03 Sep 2015
Posts: 2

View user's profile Send private message Send e-mail

PWM controlled through I2C BH1750
PostPosted: Sat Dec 12, 2015 12:26 am     Reply with quote

Hello again, thanks for your replies, PCM programmer when I turn on the circuit, the I2C communication works and then the PWM start at 0%, then it rises to 99% and then turns 0% again, the I2C still works I tested it with my oscilloscope but the PWM does nothing, tested with the oscilloscope too.

So, I have tried what you said, but with an lcd instead of teraterm and I have obtained the following:

PRESET=0
LUX=0
PWM doesn't shown

But surprisingly, after a few minutes I obtain this:

PRESET=0
LUX=42
PWM=65365

Here is the code with the printf statements and the lcd:

Code:

#include <16f877a.h>
#use delay (clock=20000000)
#fuses HS
#fuses NOWDT
#fuses NOLVP
#fuses NOPROTECT

#include <lcd.c>
#define LCD_ENABLE_PIN  PIN_D0
#define LCD_RS_PIN      PIN_D1
#define LCD_RW_PIN      PIN_D2
#define LCD_DATA4       PIN_D4
#define LCD_DATA5       PIN_D5
#define LCD_DATA6       PIN_D6
#define LCD_DATA7       PIN_D7

#use I2C(MASTER, sda=PIN_C4, scl=PIN_C3)
#define PWR_DOWN       0x00
#define PWR_ON         0x01
#define RESET          0X07
#define MODE_HIGH_RES1 0X10
#define MODE_HIGH_RES2 0X11
#define MODE_LOW_RES   0x13
#define ADDR_HIGH_R    0xB9
#define ADDR_HIGH_W    0xB8
#define ADDR_LOW_R     0X47
#define ADDR_LOW_W     0x46


unsigned long MUESTRA1,MUESTRA2,LUX,PWM,PRESET;
char HB,LB;

//funcion para activar y configurar el modulo sensor de luminosidad
void BH1750_init()
{
 I2C_START();
 I2C_WRITE(ADDR_LOW_W);
 I2C_WRITE(PWR_ON);
 I2C_WRITE(RESET);
 I2C_WRITE(ADDR_LOW_W);
 I2C_WRITE(MODE_HIGH_RES1);
 I2C_STOP();
 delay_ms(100);
}


void main()
{
 //configuro canal PWM y BH1750
 lcd_init();
 setup_ccp1(CCP_PWM);
 setup_timer_2(T2_DIV_BY_4,83,1);
 BH1750_init();
 
 //inicio canal PWM en 0 y luego lo subo al 99% aprox.
 set_pwm1_duty(0L);
 set_pwm1_duty(82L);
 
 //guardo la maxima luminosidad de la luminaria en PRESET
 I2C_START();
 I2C_WRITE(ADDR_LOW_R);
 HB=I2C_READ(1);
 LB=I2C_READ(0);
 I2C_STOP();
 MUESTRA1=make16(HB,LB);
 PRESET=(MUESTRA1/1.2);
 lcd_putc("\f");
 lcd_gotoxy(1,1);
 printf(lcd_putc,"PRESET=%lu",PRESET);

 
 
 //bajo el valor del PWM a 0, como al inicio
 set_pwm1_duty(0L);
 
 while(1)
 {
  I2C_START();
  I2C_WRITE(ADDR_LOW_R);
  HB=I2C_READ(1);
  LB=I2C_READ(0);
  I2C_STOP();
  MUESTRA2=make16(HB,LB);
  LUX=(MUESTRA2/1.2);
  lcd_gotoxy(1,2);
  printf(lcd_putc,"LUX=%lu",LUX);
 
  PWM=0;
 
  if(LUX<PRESET)
  {
   PWM=PWM+1;
   set_pwm1_duty(PWM);
   lcd_gotoxy(8,2);
   printf(lcd_putc,"PWM=%lu",PWM);
  }
  else if(LUX>PRESET)
  {
   PWM=PWM-1;
   set_pwm1_duty(PWM);
   lcd_gotoxy(8,2);
   printf(lcd_putc,"PWM=%lu",PWM);
  }
 
 }
}


Jay, I understand what you said, but I don't know how to check it, I'm still a noob. Sad
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

Re: PWM controlled through I2C BH1750
PostPosted: Mon Dec 14, 2015 10:46 am     Reply with quote

stratogama wrote:

So, I have tried what you said, but with an lcd instead of teraterm and I
have obtained the following:

PRESET=0
LUX=0
PWM doesn't show

Look at your code below. You don't have an if() statement that covers
the case where LUX == PRESET. You initially set PWM = 0. If LUX == 0,
then both if() statements below will be ignored. PWM will not show.
Code:

PWM=0;
 
  if(LUX<PRESET)
  {
   PWM=PWM+1;
   set_pwm1_duty(PWM);
   lcd_gotoxy(8,2);
   printf(lcd_putc,"PWM=%lu",PWM);
  }
  else if(LUX>PRESET)
  {
   PWM=PWM-1;
   set_pwm1_duty(PWM);
   lcd_gotoxy(8,2);
   printf(lcd_putc,"PWM=%lu",PWM);
  }

So the question is, why does LUX stay at 0 ? Maybe there is something
wrong with your hardware design. Or your software driver for the BH1750 ?
stratogama wrote:

the I2C still works I tested it with my oscilloscope

I would test the i2c by running the BH1750 driver and looking at the
lux values returned by the driver. I would not use an LCD for this.
I would use RS232 and TeraTerm (or some other terminal program).
When you use a terminal program, it displays a record of the past values.
You can examine the data carefully. With an LCD, there is no past
record. There are not enough lines in the LCD for it.

stratogama wrote:

But surprisingly, after a few minutes I obtain this:

PRESET=0
LUX=42
PWM=65365

It's not that surprising. If LUX is greater than PRESET, the 'PWM'
variable will decrement by 1. It will go from 0 to -1, which is 0xFFFF,
which is 65535. And PRESET is 0, so if LUX goes to 1 or anything, you
will get 65535 as the PWM value.

If LUX remains > 0, then PWM will continue to decrement, and you will
get PWM=65365 at some point.

The lines in bold below show this:
Quote:

PWM=0;

if(LUX<PRESET)
{
PWM=PWM+1;
set_pwm1_duty(PWM);
lcd_gotoxy(8,2);
printf(lcd_putc,"PWM=%lu",PWM);
}
else if(LUX>PRESET) // if LUX > 0
{
PWM=PWM-1;
set_pwm1_duty(PWM);
lcd_gotoxy(8,2);
printf(lcd_putc,"PWM=%lu",PWM);
}
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group