|
|
View previous topic :: View next topic |
Author |
Message |
juca85
Joined: 28 Jun 2020 Posts: 8 Location: Colombia
|
Help with this code for APDS-9930 proximity sensor |
Posted: Sun Jun 28, 2020 12:58 am |
|
|
Hello i need help with this code.
This code appears on the sensor data sheet APDS-9930:
Code: | WriteRegData(uint8 reg, uint8 data)
{
m_I2CBus.WriteI2C(0x39, 0x80 | reg, 1, &data);
} |
0x39 is the sensor address and 0x80 is a command register for repeated byte or increment byte protocol, the register doesn't have an address.
In Arduino library appears this code. I don't know how translate that:
Code: | bool APDS9930::wireWriteDataByte(uint8_t reg, uint8_t val)
{
Wire.beginTransmission(0x39);
Wire.write(reg | 0x80);
Wire.write(val);
if( Wire.endTransmission() != 0 ) {
return false;
}
return true;
} |
This is how the code should be but it doesn't work. I don't know where to put 0x80 instruction:
Code: | void write_reg(int reg,int val)
{
i2c_Start();
i2c_write(0x39);
i2c_write(reg);
i2c_write(val);
i2c_stop();
delay_ms(70);
return;
} |
Please help with this code!!!
Datasheet:
https://docs.broadcom.com/doc/AV02-3190EN
Library Arduino:
https://github.com/Depau/APDS9930 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Sun Jun 28, 2020 1:38 am |
|
|
First key thing is this:
0x39
Wrong....
The PIC uses an 8bit address. Means that translating from any device using
the 7bit address format, you have to multiply the number by 2.....
Then the register does have an address. It just happens to be zero.
Code: |
//You need to include <stdint.h> to give definitions for uint8_t etc..
//before this.
#define APDADDR (0x39*2)
BOOLEAN APDS9930wireWriteDataByte(uint8_t reg, uint8_t val)
{
int1 ack;
I2C_start();
I2C_write(APDADDR);
I2C_write(reg | 0x80);
ack=I2C_write(val);
I2C_stop();
if( ack==0)
return false;
return true;
}
|
Why the delay?. Not wanted or needed.
The reason your code didn't work was the device address.... |
|
|
juca85
Joined: 28 Jun 2020 Posts: 8 Location: Colombia
|
|
Posted: Sun Jun 28, 2020 5:48 pm |
|
|
Ttelmah wrote: | First key thing is this:
0x39
Wrong....
The PIC uses an 8bit address. Means that translating from any device using
the 7bit address format, you have to multiply the number by 2.....
Then the register does have an address. It just happens to be zero.
//You need to include <stdint.h> to give definitions for uint8_t etc..
//before this.
#define APDADDR (0x39*2)
BOOLEAN APDS9930wireWriteDataByte(uint8_t reg, uint8_t val)
{
int1 ack;
I2C_start();
I2C_write(APDADDR);
I2C_write(reg | 0x80);
ack=I2C_write(val);
I2C_stop();
if( ack==0)
return false;
return true;
}
Why the delay?. Not wanted or needed.
The reason your code didn't work was the device address.... |
No, that is not the problem, check all my code. Write address is 0x72, is ok.
Code: | #include <18F4550.h>
#fuses NOMCLR, INTRC_IO, NOWDT, NOPROTECT, NOLVP
#use DELAY(CLOCK=8M)
#use standard_io(b)
#use I2C(master, sda=PIN_B0, scl=PIN_B1)
/* Command register modes */
#define REPEATED_BYTE 0x80
#define AUTO_INCREMENT 0xA0
/* Interrupt clear values */
#define CLEAR_PROX_INT 0xE5
#define CLEAR_ALS_INT 0xE6
#define CLEAR_ALL_INT 0xE7
/* Default values */
#define DEFAULT_ATIME 0xFF
#define DEFAULT_WTIME 0xFF
#define DEFAULT_PTIME 0xFF
#define DEFAULT_PPULSE 0x08
#define DEFAULT_POFFSET 0 // 0 offset
#define DEFAULT_CONFIG 0
#define DEFAULT_CONTROL 0X20 //PDRIVE=0;PDIODE=2;PGAIN=0;PGAIN=0
#define DEFAULT_PERS 0x22 // 2 consecutive prox or ALS for int.
/* Acceptable parameters for Enable */
#define POWER_ALL 0x7F
#define POWER_OFF 0x00
#define POWER_PROXIMITY 0x2D
#define POWER_ALS 0x5B
#define ID_W 0x72
#define ID_R 0X73
/* APDS-9930 Direcciones de registro */
#define ENABLE 0x00
#define ATIME 0x01
#define PTIME 0x02
#define WTIME 0x03
#define AILTL 0x04
#define AILTH 0x05
#define AIHTL 0x06
#define AIHTH 0x07
#define PILTL 0x08
#define PILTH 0x09
#define PIHTL 0x0A
#define PIHTH 0x0B
#define PERS 0x0C
#define CONFIG 0x0D
#define PPULSE 0x0E
#define CONTROL 0x0F
#define ID 0x12
#define STATUS 0x13
#define CH0DATAL 0x14
#define CH0DATAH 0x15
#define CH1DATAL 0x16
#define CH1DATAH 0x17
#define PDATAL 0x18
#define PDATAH 0x19
#define POFFSET 0x1E
#define LED PIN_B4 //
float proximity_data = 0;
int isr_flag = 0;
int read_reg(int reg)
{
i2c_start();
i2c_write(ID_W);
i2c_write(reg | REPEATED_BYTE);
i2c_start();
i2c_write(ID_R);
int8 val=i2c_read(0);
i2c_stop();
return(val);
}
void write_reg(int reg,int val)
{
i2c_Start();
i2c_write(ID_W);
i2c_write(reg | REPEATED_BYTE);
i2c_write(val);
i2c_stop();
delay_ms(70);
return;
}
void cmd(int val)
{
i2c_Start();
i2c_write(ID_W);
i2c_write(val);
i2c_stop();
delay_ms(70);
return;
}
int16 get_value(int reg_h,int reg_l)
{
int8 data_h=read_reg(reg_h);
int8 data_l=read_reg(reg_l);
int16 datahl=make16(data_h,data_l);
return(datahl);
}
void blink_led (int8 valor)
{
int8 x=0;
for (x=1;x<=valor;x++)
{
output_high(LED);
delay_ms(500);
output_low(LED);
delay_ms(500);
}
return;
}
void test(void)
{
int8 i=0;
i=read_reg(ID);
if (i==0x39 || i==0x12)
blink_led(5);
else
blink_led(4);
return;
}
void begin(void)
{
delay_ms(1000);
write_reg(ENABLE,POWER_OFF);
write_reg(ATIME,DEFAULT_ATIME);
write_reg(PTIME,DEFAULT_PTIME);
write_reg(WTIME,DEFAULT_WTIME);
write_reg(PPULSE,DEFAULT_PPULSE);
write_reg(POFFSET,DEFAULT_POFFSET);
write_reg(CONFIG,DEFAULT_CONFIG);
write_reg(CONTROL,DEFAULT_CONTROL);
write_reg(AILTL,0xFF);
write_reg(AILTH,0xFF);
write_reg(AIHTL,0x00);
write_reg(AIHTH,0x00);
write_reg(PILTL,0x00);
write_reg(PILTH,0x00);
write_reg(PIHTL,0x32);
write_reg(PIHTH,0x00);
write_reg(PERS,DEFAULT_PERS);
blink_led(3);
delay_ms(1000);
return;
}
#int_EXT2
void ext_isr()
{
isr_flag = 1;
}
void main(void)
{
setup_oscillator(OSC_8MHZ);
set_tris_b(0x0F);
enable_interrupts(GLOBAL); //Habilita interrupciones
enable_interrupts(INT_EXT2_L2H); //Habilita interrupcion RB
delay_ms(1000);
test(); //check id reg
begin(); //config start
write_reg(CONTROL,0x24); //define Pgain 2x
write_reg(ENABLE,POWER_ALL);
write_reg(PILTL,0x00);
write_reg(PILTH,0x00);
write_reg(PIHTL,0x58);
write_reg(PIHTH,0x02); //Proximity interrupt high threshold 600
blink_led(2);
delay_ms(1000);
while(true)
{
if (isr_flag)
{
output_high(LED);
delay_ms(3000);
output_low(LED);
cmd(CLEAR_PROX_INT);
isr_flag = 0;
}
}
} |
i think is the problem is cmd register or i don't know, need help, the register 0x00 is Enable, cmd doen't have address, see yourself:
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Sun Jun 28, 2020 10:21 pm |
|
|
Your original code showed:
i2c_write(0x39);
The command register is always selected, when you start a write
transaction.
So sequence is:
start
Write device address
Write to command register
......
Quote: |
During a write operation, the first byte written is a command byte followed by data. In a combined protocol, the first byte written is the command byte followed by reading a series.
|
|
|
|
juca85
Joined: 28 Jun 2020 Posts: 8 Location: Colombia
|
|
Posted: Sun Jun 28, 2020 10:45 pm |
|
|
Ttelmah wrote: | Your original code showed:
i2c_write(0x39);
The command register is always selected, when you start a write
transaction.
So sequence is:
start
Write devive address
Write to command register
......
Quote: |
During a write operation, the first byte written is a command byte followed by data. In a combined protocol, the first byte written is the command byte followed by reading a series.
|
|
OK my bad in the first code, i get it, that part is ready, thanks. Now please help with the configuration of ports in the code. The sensor has six pins 1-VL, 2-GND, 3-VCC, 4-SCL, 5-SDA, 6-INT.
I connected SDA to RB0, SCL to RB1 with pull-up resistor 4.7k.
The INT interrupt pin sensor is connected to RB2 with pull-up resistor 10k, and the port is set interrupt ext2, and last RB4 is an LED for show the interrupt for proximity,
The question is how to configure the port B of the PIC to work fine? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Mon Jun 29, 2020 12:49 am |
|
|
There is a glaring problem.
You have a 5v PIC. This is a 3.3v device.
If you have connected your PIC Vcc to this, you have probably destroyed
the chip. It is rated for 3.8v _max_.
The I2C inputs are rated to go up to it's Vcc maximum.
Potentially you can use it on your PIC, with a separate 3.3v supply, pull-
ups to 3.3v, and specifying the PIC I2C using the 'SMBUS' option, which
turns 'down' the voltage the PIC will expect on the I2C bus (the Arduino
inputs run at this lower voltage by default). Make your pull-ups lower
(1K2R), 4K7, even at 5v, is not adequate for 400K, and at 3.3v, is even
worse.
Get your hardware right first.
With your hardware sorted, your register read and writes, look OK.
Change your I2C setup, to:
#use I2C(master, FAST=400000, I2C1, SMBUS)
Then use PCM Programmer's I2C bus scan program, and verify that with
this setting, the chip is being seen on addresses 0x72 and 0x73.
This should always be treated as the 'first thing to do' with I2C.
It's in the code library.
Personally, I would add a 'read_word' function as:
Code: |
int16 read_word(int reg)
{
int8 low;
int16 whole;
i2c_start();
i2c_write(ID_W);
i2c_write(reg | AUTO_INCREMENT);
i2c_start();
i2c_write(ID_R);
low=i2c_read();
whole=make16(i2c_read(0),low);
i2c_stop();
return(whole);
}
|
Then the pseudo code on page 15, can be used as a starting point for
the setup, with this replacing the 'read_word' function used in this. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Mon Jun 29, 2020 7:36 am |
|
|
sigh.. this post is WHY we need to see a small, complete, compilable program in the FIRST posting.
As Mr. T correctly points out 5 volt PIC and 3 volt peripherals don't 'play well together' !!
While there are 'tricks' like SMB....it's often easier to just use an 'L' version PIC or one with 3-5v ability. Using 'logic level converters' is anothe roption but 'messy'. More parts, more wires, more to go wrong.....
Jay |
|
|
juca85
Joined: 28 Jun 2020 Posts: 8 Location: Colombia
|
|
Posted: Mon Jun 29, 2020 11:05 am |
|
|
Ttelmah wrote: | There is a glaring problem.
You have a 5v PIC. This is a 3.3v device.
If you have connected your PIC Vcc to this, you have probably destroyed
the chip. It is rated for 3.8v _max_.
The I2C inputs are rated to go up to it's Vcc maximum.
Potentially you can use it on your PIC, with a separate 3.3v supply, pull-
ups to 3.3v, and specifying the PIC I2C using the 'SMBUS' option, which
turns 'down' the voltage the PIC will expect on the I2C bus (the Arduino
inputs run at this lower voltage by default). Make your pull-ups lower
(1K2R), 4K7, even at 5v, is not adequate for 400K, and at 3.3v, is even
worse.
Get your hardware right first.
With your hardware sorted, your register read and writes, look OK.
Change your I2C setup, to:
#use I2C(master, FAST=400000, I2C1, SMBUS)
Then use PCM Programmer's I2C bus scan program, and verify that with
this setting, the chip is being seen on addresses 0x72 and 0x73.
This should always be treated as the 'first thing to do' with I2C.
It's in the code library.
Personally, I would add a 'read_word' function as:
Code: |
int16 read_word(int reg)
{
int8 low;
int16 whole;
i2c_start();
i2c_write(ID_W);
i2c_write(reg | AUTO_INCREMENT);
i2c_start();
i2c_write(ID_R);
low=i2c_read();
whole=make16(i2c_read(0),low);
i2c_stop();
return(whole);
}
|
Then the pseudo code on page 15, can be used as a starting point for
the setup, with this replacing the 'read_word' function used in this. |
Thanks for the code is necessary to read all the data. I change the resistors for 1,2k in the i2c ports. I use LM1117T-3.3. I use 3.3volts in both PIC and sensor, still not work. Help me with the proper configuration of the ports in and outs. Maybe that's the problem. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Mon Jun 29, 2020 11:50 am |
|
|
Your PIC is not rated to run at 3.3v.
Hence the comments about this.
The 18F4550, is rated for 4.2v _minimum_.
To run below this you need the LF version (PIC18LF4550). |
|
|
juca85
Joined: 28 Jun 2020 Posts: 8 Location: Colombia
|
|
Posted: Mon Jun 29, 2020 11:19 pm |
|
|
Ttelmah wrote: | Your PIC is not rated to run at 3.3v.
Hence the comments about this.
The 18F4550, is rated for 4.2v _minimum_.
To run below this you need the LF version (PIC18LF4550).
|
Yes you right!, but the same doesn't work, how to configure port B ?
With trisb the interrupt is in, sda? scl? led is out. I use standard i/o, but i am not sure how! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Tue Jun 30, 2020 12:18 am |
|
|
If you configure the I2C as I show, the PortB configuration is all done. |
|
|
juca85
Joined: 28 Jun 2020 Posts: 8 Location: Colombia
|
|
Posted: Tue Jun 30, 2020 12:38 am |
|
|
Ttelmah wrote: | If you configure the I2C as I show, the PortB configuration is all done. |
The interrupt pin is necesary set as input? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Tue Jun 30, 2020 1:14 am |
|
|
Pins always wake set as inputs. Unless you switch them, or automatic
switching is done (as will happen when you setup the I2C), these settings
remain. |
|
|
juca85
Joined: 28 Jun 2020 Posts: 8 Location: Colombia
|
|
Posted: Tue Jun 30, 2020 2:20 pm |
|
|
Ttelmah wrote: | Pins always wake set as inputs. Unless you switch them, or automatic
switching is done (as will happen when you setup the I2C), these settings
remain. |
ok i connect a LCD 20x2 for see the write and read reg and is all good, works perfect, maybe i made something wrong with the configuration, the interrupt of the sensor doesn't trigger when reach the high threshold. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Wed Jul 01, 2020 12:29 am |
|
|
There are a huge number of things that affect how/when the interrupt
will trigger.
You have first of all, the PIEN, and AIEN fields to determine if the
interrupt is enabled. Then the upper and lower limit fields. Then the
persistence fields determine how long the trigger must exist before the
interrupt will fire. At this point it will optionally put the chip to sleep
as well.
AIL, AIH, PIL, PIH, PERS all need to be set correctly. Also you should
clear the interrupt in case is has been set on boot. |
|
|
|
|
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
|