Gambas + PIGPIO + I2C + ADS1115 A/D Chip

Ask about the individual Gambas components here.
Post Reply
User avatar
Askjerry
Posts: 24
Joined: Saturday 18th August 2018 9:06pm
Location: Kyle, Texas, USA
Contact:

Gambas + PIGPIO + I2C + ADS1115 A/D Chip

Post by Askjerry » Saturday 13th March 2021 1:01am

:roll: Honestly... I beat at a problem for a while before I ask for help... but I'm stumped as to what I am doing wrong here.

The ADS1115 Datasheet specifically tells you what to put in to get a reading... and I think I'm doing just that. The problem is... I'm not getting any errors, but the chip constantly reports MSB = 0 and LSB = 0 and it does not matter if I tie the AN0 pin to 3.3vdc or Ground.

I have three outputs... each is a Textbox and my routine sends the data there. A TIMER1 pings the routine once a second.
I also have text printing to the debugger area so I know it is running the routine. I have tried putting the data in as binary &b00000000& as HEX &H00& and as a plain old decimal. Same thing.

here is the code... maybe I'm just too close... overlooking a blatant error.

Code: Select all

'-------------------------------------------------------------------------------------------------
' Gambas3 ADS1115 Test Program Version 1.0
'-------------------------------------------------------------------------------------------------
' Load the pigpio library
Library "/usr/local/lib/libpigpio"
'-------------------------------------------------------------------------------------------------
' Library Setup Section
'-------------------------------------------------------------------------------------------------
Public Extern gpioInitialise() As Integer   'call at start of program to initialise 
Public Extern gpioTerminate() As Integer    'call at end of program to release resources and terminate threads
Public Extern gpioVersion() As Integer
Public Extern gpioHardwareRevision() As Integer
Public Extern gpioSetMode(iPin As Integer, iMode As Integer) As Integer
Public Extern gpioRead(iPin As Integer) As Integer
Public Extern gpioWrite(iPin As Integer, iLevel As Integer) As Integer
Public Extern gpioSetPullUpDown(iPin As Integer, iMode As Integer) As Integer
Public Extern gpioServo(servo_pin As Integer, servo_value As Integer) As Integer
'-------------------------------------------------------------------------------------------------
Public Extern i2cOpen(i2cBus As Integer, i2cAddress As Integer, i2cFlags As Integer) As Integer
Public Extern i2cClose(i2c_handle As Integer)
Public Extern i2cWriteByte(i2c_handle As Integer, i2cByte As Byte) As Integer
Public Extern i2cReadByte(i2c_handle As Integer) As Integer
Public Extern i2cWriteWordData(i2c_handle As Integer, i2cReg As Integer, i2cWord As Integer) As Integer
Public Extern i2cReadWordData(i2c_handle As Integer, i2cReg As Integer) As Integer
'-------------------------------------------------------------------------------------------------
' Define constants
'-------------------------------------------------------------------------------------------------
Const PI_INPUT As Integer = 0
Const PI_OUTPUT As Integer = 1
Const PI_RESISTOR_UP As Integer = 2
Const PI_RESISTOR_DOWN As Integer = 1
Const PI_RESISTOR_OFF As Integer = 0
'-------------------------------------------------------------------------------------------------
' Define Public Variables
'-------------------------------------------------------------------------------------------------
Public i2c_handle As Integer = 0
'-------------------------------------------------------------------------------------------------

Public Sub Form_Open()
  Dim intReply As Integer
  intReply = gpioInitialise()
  
  If intReply < 0 Then
    DSP_Software_Stat.Text = "Failed: must be run as root"
  Else
    DSP_Software_Stat.Text = "OK. Initialised: PIGPIO Version Number: " & intReply
  Endif
'-------------------------------------------------------------------------------------------------
' Open I2C Port on BUS 1 for the ADS1115 A/D Chip
'-------------------------------------------------------------------------------------------------
Print "Open the i2C port on Bus 1 for the ADS1115 A/D Chip."
i2c_handle = i2copen(1, &H48&, 0)
' Configure ADS1115 for constant conversion mode, Address 100, Port AN0
' - First byte:  0b10010000(first 7 - bit I2C address followed by a low R / W bit)
    i2cWriteByte(i2c_handle, &H90&) 
' – Second byte: 0b00000001 (points to Config register)
    i2cWriteByte(i2c_handle, &H01&) 
' – Third byte:  0b10000100 (MSB of the Config register to be written)
    i2cWriteByte(i2c_handle, &H84&) 
' – Fourth byte: 0b10000011 (LSB of the Config register to be written)
    i2cWriteByte(i2c_handle, &H83&) 
Print "ADS1115 set to port AN0 and GND in continious read mode."
'-------------------------------------------------------------------------------------------------
' Other Tasks
'-------------------------------------------------------------------------------------------------
End

Public Sub Form_Close()
gpioTerminate()
End

Public Sub Timer_1_Timer()
 Dim LSB As Byte
 Dim MSB As Byte
 Print "==============================================="
 Print "I2C Read Request Initiated"
 ' The chip was already set when the form Opened.
 ' Write to the POINTER REGISTER
 ' - First byte:  0b10010000 (first 7 - bit I2C address followed by a low R / W bit)
 i2cWriteByte(i2c_handle, &H90&)
 ' – Second byte: 0b00000000 (points to Conversion register)
 i2cWriteByte(i2c_handle, &H00&)
 Print "Pointer Written."
 ' Read the CONVERSION register.
 ' - First byte: WRITE 0b10010001 (first 7 - bit I2C address followed by a high R / W bit)
     i2cWriteByte(i2c_handle, &H90&) ' Address and HIGH (Read) bit
 Print "Address sent, pushed READ command."
  ' – Second byte: READ the ADS111x response with the MSB of the Conversion register
      MSB = i2cReadByte(i2c_handle)
  ' – Third byte:  READ the ADS111x response with the LSB of the Conversion register
      LSB = i2cReadByte(i2c_handle)
 Print "Data Revovered. MSB = " & MSB & " LSB = " & LSB
 DSP_MSB.Text = Str(MSB)
 DSP_LSB.Text = Str(LSB)
 DSP_DEC.Text = Str((MSB * 256) + LSB)
End
I have an I2C 8-Bit output chip... maybe I'll install it and try lighting up some LEDs. I've done I2C before with both chips in PYTHON... but that was a different command structure. I really like PIGPIO and want to get this to work... all my other functions INPUT/OUTPUT/PWM/SERVO all work great.

Thanks,
Jerry

User avatar
stevedee
Posts: 431
Joined: Monday 20th March 2017 6:06pm

Re: Gambas + PIGPIO + I2C + ADS1115 A/D Chip

Post by stevedee » Saturday 13th March 2021 8:51am

Askjerry wrote:
Saturday 13th March 2021 1:01am
...Datasheet specifically tells you what to put in to get a reading... and I think I'm doing just that. The problem is... I'm not getting any errors...
Well, you might be getting errors that you are not checking for.

I'm probably being an old woman, but I'd check the return values for all the write commands you are using...just in case.
Example:-
   
         intReply =  i2cWriteByte(i2c_handle, &H90&)
         If intReply <> 0 Then
           'some kind of error

User avatar
Askjerry
Posts: 24
Joined: Saturday 18th August 2018 9:06pm
Location: Kyle, Texas, USA
Contact:

Re: Gambas + PIGPIO + I2C + ADS1115 A/D Chip

Post by Askjerry » Monday 26th April 2021 1:34am

I swear this chip is going to drive me crazy... a short drive actually.

After not getting the ADS1115 to work properly I decided to try another IC that I am familiar with, the PCF8574 Extender Chip.
The datasheet is here: https://www.ti.com/lit/ds/symlink/pcf8574.pdf

Page 9 shows the address as follows: 0100aaar where aaa is the address set by jumpers, and r is 0 to 1 depending on if you want to write (0) or read (1). As my chip address pins are wired to the ground, it would make the address to be 0100 0000 and I would have expected the number to be left to right &H20&. However, that failed... it was actually &H02& as you have to read the two numbers left to right with the bits being 1248.

Ok... I got that to work just fine. I was able to toggle some LEDs on and off proving the i2c commands work.
Here is a code snippet.

Code: Select all

Case 1
      'Activate PCF8574 Extender Chip
      intReply = i2cOpen(1, &H20&, 0)
      DSP_EXT_STAT.Text = "ACTIVE"
    Case 2
      'Send out 1111 1111
      DSP_EXT_STAT.Text = "WRITE FF"
      intReply = i2cWriteByte(i2c_handle, &Hff&) 
      DSP_EXT_VALUE.Text = "1 1 1 1 1 1 1 1" 
    Case 3
      'Send out 0000 0000
      DSP_EXT_STAT.Text = "WRITE 00"
      intReply = i2cWriteByte(i2c_handle, &H00&) 
      DSP_EXT_VALUE.Text = "0 0 0 0 0 0 0 0" 
    Case 4
      i2cClose(i2c_handle)
      ' Close PCF8574
      DSP_EXT_STAT.Text = "IDLE"
Taking what I just learned... I wanted to apply it to the ADS1115 chip as it is necessary for the project I am working on to read multiple sensors.

The PDF for the ADS1115: https://www.ti.com/lit/ds/symlink/ads1115.pdf

Jumping into page 35, they give you the proper sequence of codes to set the unit up for Port 1, Address 0, Continuous mode, 3.5v which is exactly what I need for the first sensor.

1.Writeto Config register:
– First byte:0b10010000 (first7-bit I2C address followed by a low R/W bit)
– Second byte:0b00000001 (points to Config register)
– Third byte:0b10000100 (MSB of the Config register to be written)
– Fourth byte:0b10000011 (LSB of the Config register to be written)
2.Write to Address Pointer register:
– First byte:0b10010000 (first7-bit I2C address followed by a low R/W bit)
– Second byte:0b00000000 (points to Conversion register)
3.Read Conversion register:
– First byte:0b10010001 (first7-bit I2C address followed by a high R/W bit)
– Second byte: the ADS111x response with the MSB of the Conversion register
– Third byte: the ADS111x response with the LSB of the Conversion register

So we look at the numbers... and convert them the same way.
1001 0000 --> 09
0000 0001 --> 80
1000 0100 --> 21
1000 0011 --> C1
-------------
1001 0000 --> 09
0000 0000 --> 00
-------------
1001 0001 --> 89

The code snippet works out to

Code: Select all

Case 5
      'Activate ADS1115
      intReply = i2cOpen(1, &H09&, 0)
      DSP_ADS_STAT.text = "ACTIVE"
    Case 6
      'Write Configuration
      DSP_ADS_STAT.Text = "CONFIG"
      intReply = i2cWriteByte(i2c_handle, &H09&) 
      intReply = i2cWriteByte(i2c_handle, &H80&) 
      intReply = i2cWriteByte(i2c_handle, &H21&) 
      intReply = i2cWriteByte(i2c_handle, &HC1&) 
    Case 7
      'Set Pointer
      DSP_ADS_STAT.Text = "POINTER"
      intReply = i2cWriteByte(i2c_handle, &H09&) 
      intReply = i2cWriteByte(i2c_handle, &H00&) 
    Case 8
      'Read Data
      DSP_ADS_STAT.Text = "READ"
      intReply = i2cWriteByte(i2c_handle, &H89&) 
      intReply = i2cReadByte(MSB)
      intReply = i2cReadByte(LSB)
      DSP_MSB.Text = MSB
      DSP_LSB.Text = LSB
    Case 9
      'Close ADS1115
      DSP_ADS_STAT.Text = "IDLE"
      i2cClose(i2c_handle)
And the entire program being:

Code: Select all

' Gambas class file

'-------------------------------------------------------------------------------------------------
' Gambas3 I2C Test Program Version 1.0
'-------------------------------------------------------------------------------------------------
' Load the pigpio library
  Library "/usr/local/lib/libpigpio"
'-------------------------------------------------------------------------------------------------
' Library Setup Section
'-------------------------------------------------------------------------------------------------
Public Extern gpioInitialise() As Integer   'call at start of program to initialise 
Public Extern gpioTerminate() As Integer    'call at end of program to release resources and terminate threads
Public Extern gpioVersion() As Integer
Public Extern gpioHardwareRevision() As Integer
Public Extern gpioSetMode(iPin As Integer, iMode As Integer) As Integer
Public Extern gpioRead(iPin As Integer) As Integer
Public Extern gpioWrite(iPin As Integer, iLevel As Integer) As Integer
Public Extern gpioSetPullUpDown(iPin As Integer, iMode As Integer) As Integer
Public Extern gpioServo(servo_pin As Integer, servo_value As Integer) As Integer
'-------------------------------------------------------------------------------------------------
Public Extern i2cOpen(i2cBus As Integer, i2cAddress As Integer, i2cFlags As Integer) As Integer
Public Extern i2cClose(i2c_handle As Integer)
Public Extern i2cWriteByte(i2c_handle As Integer, i2cByte As Byte) As Integer
Public Extern i2cReadByte(i2c_handle As Integer) As Integer 
Public Extern i2cWriteWordData(i2c_handle As Integer, i2cReg As Integer, i2cWord As Integer) As Integer
Public Extern i2cReadWordData(i2c_handle As Integer, i2cReg As Integer) As Integer
'-------------------------------------------------------------------------------------------------
' Define constants
'-------------------------------------------------------------------------------------------------
Const PI_INPUT As Integer = 0
Const PI_OUTPUT As Integer = 1
Const PI_RESISTOR_UP As Integer = 2
Const PI_RESISTOR_DOWN As Integer = 1
Const PI_RESISTOR_OFF As Integer = 0
'-------------------------------------------------------------------------------------------------
' Define Public Variables
'-------------------------------------------------------------------------------------------------
Public i2c_handle As Integer = 0
Public intReply As Integer = 0
Public tick_tock As Integer = 0 ' A counting number for the timer routine.
Public MSB As Integer
Public LSB As Integer
Public BUS As Integer

'-------------------------------------------------------------------------------------------------

Public Sub Form_Open()
  intReply = gpioInitialise()
    If intReply < 0 Then
      DSP_Software_Stat.Text = "Failed: Program must be run as root"
    Else
      DSP_Software_Stat.Text = "PIGPIO Version Number [ " & intReply & " ] Started Ok"
    Endif
  
  'Set up Pin 19 to operate the LED
  gpioSetMode(19, PI_OUTPUT)
  
  '-------------------------------------------------------------------------------------------------
  ' Other Tasks
  '-------------------------------------------------------------------------------------------------
End

Public Sub Form_Close()
  gpioTerminate()
End
'-------------------------------------------------------------------------------------------------

Public Sub Timer_1_Timer()
tick_tock = tick_tock + 1
If tick_tock > 9 Then tick_tock = 1
Print "Cycle = " & tick_tock;
DSP_CYCLE.Text = tick_tock
  Select Case tick_tock
    
    Case 1
      'Activate PCF8574 Extender Chip
      intReply = i2cOpen(1, &H20&, 0)
      DSP_EXT_STAT.Text = "ACTIVE"
    Case 2
      'Send out 1111 1111
      DSP_EXT_STAT.Text = "WRITE FF"
      intReply = i2cWriteByte(i2c_handle, &Hff&) 
      DSP_EXT_VALUE.Text = "1 1 1 1 1 1 1 1" 
    Case 3
      'Send out 0000 0000
      DSP_EXT_STAT.Text = "WRITE 00"
      intReply = i2cWriteByte(i2c_handle, &H00&) 
      DSP_EXT_VALUE.Text = "0 0 0 0 0 0 0 0" 
    Case 4
      i2cClose(i2c_handle)
      ' Close PCF8574
      DSP_EXT_STAT.Text = "IDLE"
    Case 5
      'Activate ADS1115
      intReply = i2cOpen(1, &H09&, 0)
      DSP_ADS_STAT.text = "ACTIVE"
    Case 6
      'Write Configuration
      DSP_ADS_STAT.Text = "CONFIG"
      intReply = i2cWriteByte(i2c_handle, &H09&) 
      intReply = i2cWriteByte(i2c_handle, &H80&) 
      intReply = i2cWriteByte(i2c_handle, &H21&) 
      intReply = i2cWriteByte(i2c_handle, &HC1&) 
    Case 7
      'Set Pointer
      DSP_ADS_STAT.Text = "POINTER"
      intReply = i2cWriteByte(i2c_handle, &H09&) 
      intReply = i2cWriteByte(i2c_handle, &H00&) 
    Case 8
      'Read Data
      DSP_ADS_STAT.Text = "READ"
      intReply = i2cWriteByte(i2c_handle, &H89&) 
      intReply = i2cReadByte(MSB)
      intReply = i2cReadByte(LSB)
      DSP_MSB.Text = MSB
      DSP_LSB.Text = LSB
    Case 9
      'Close ADS1115
      DSP_ADS_STAT.Text = "IDLE"
      i2cClose(i2c_handle)
      
  End Select
DSP_ERROR.Text = intReply
If intReply = 0 Then
  Print " Status: PASS"
Else
  Print " Status: FAIL Code: " & intReply
Endif

End
Except... the code doesn't work. The PCF8574 is just fine... no issues at all.
The ADS1115 Still throwing errors. I don't know why.

Sections 1 to 5 are fine.
Sections 6 to 9 fail.

I'm at the point where if someone wants to take this on, I'll send you an ADS1115 module so you can figure what I am doing wrong.
I need this to read the airflow sensor, load cells, and temperature sensors. I just don't get why it is not working.
ADS-ERROR.zip
Current ADS1115 program zipped.
(11.6 KiB) Downloaded 11 times

User avatar
stevedee
Posts: 431
Joined: Monday 20th March 2017 6:06pm

Re: Gambas + PIGPIO + I2C + ADS1115 A/D Chip

Post by stevedee » Monday 26th April 2021 7:17am

Askjerry wrote:
Monday 26th April 2021 1:34am
I swear this chip is going to drive me crazy... a short drive actually.

...The PDF for the ADS1115: https://www.ti.com/lit/ds/symlink/ads1115.pdf
Hi Jerry, I'll try to find time to look at the ADS1115 info later today.

But in the meantime, I don't understand why you are only checking the function return value (intReply) after the case statement.
This is fine for Case 1-3 & 5, but not for 6-8 where intReply will only show the return value for the last of the function calls.

I guess if you wanted to be economical with your source code you could do something like this:-
    Case 6
      'Write Configuration
      DSP_ADS_STAT.Text = "CONFIG"
      intReply = i2cWriteByte(i2c_handle, &H09&) 
      intReply += i2cWriteByte(i2c_handle, &H80&) 
      intReply += i2cWriteByte(i2c_handle, &H21&) 
      intReply += i2cWriteByte(i2c_handle, &HC1&) 
    Case 7
...but of course this will make the Fail Code description meaningless:-
Else
  Print " Status: FAIL Code: " & intReply
Endif

User avatar
Askjerry
Posts: 24
Joined: Saturday 18th August 2018 9:06pm
Location: Kyle, Texas, USA
Contact:

Re: Gambas + PIGPIO + I2C + ADS1115 A/D Chip

Post by Askjerry » Monday 26th April 2021 9:56am

It was basically just to see IF there were any failures, and if so to locate what section of the code so that I could then make more lines to specifically go into each CASE statement and drill it down. If you want me to ship you a module please let me know. It has to be something simple I'm missing... the extender chip works flawlessly, and when I was doing python programming the library function was flawless. (It operated differently however, you gave it the address and it did everything else... so I don't know all the internal workings, unfortunately.)

I need to get this working with Gambas3 because it allows me to make an incredible GUI when compared to other languages.

thanks,
Jerry

User avatar
stevedee
Posts: 431
Joined: Monday 20th March 2017 6:06pm

Re: Gambas + PIGPIO + I2C + ADS1115 A/D Chip

Post by stevedee » Monday 26th April 2021 9:13pm

Askjerry wrote:
Monday 26th April 2021 1:34am
...The datasheet is here: https://www.ti.com/lit/ds/symlink/pcf8574.pdf

Page 9 shows the address as follows: 0100aaar where aaa is the address set by jumpers, and r is 0 to 1 depending on if you want to write (0) or read (1). As my chip address pins are wired to the ground, it would make the address to be 0100 0000 and I would have expected the number to be left to right &H20&. However, that failed... it was actually &H02& as you have to read the two numbers left to right with the bits being 1248.

Ok... I got that to work just fine...
I'm sorry. I spent a couple of hours this evening looking at this, but I don't really understand how this bit works with the PCF8574.

The datasheet shows the most significant bit of a byte being sent first. But as this complies with the I2C standard, I would expect the pigpio library to take care of this, e.g. you give the write function the required address and the function sends the bits in the required order; msb to lsb

However, you have proved your code works with all bytes reversed, so I can't argue with that.

My only suggestion is to look at the Python code that you have used successfully on the ADS1115, and then try to replicate this in Gambas,

User avatar
Askjerry
Posts: 24
Joined: Saturday 18th August 2018 9:06pm
Location: Kyle, Texas, USA
Contact:

Re: Gambas + PIGPIO + I2C + ADS1115 A/D Chip

Post by Askjerry » Monday 26th April 2021 11:26pm

That's not going to work... it has something like READ_ADS(0) to read the port 0... it doesn't get into specifics as to how it does it.

I can get the extender chip to work... but not the ADS1115 chip.

Seriously... to anyone reading this... I'll send you a module if you want to give it a shot... I need to get this working and don't know where else to turn.

Jerry

User avatar
stevedee
Posts: 431
Joined: Monday 20th March 2017 6:06pm

Re: Gambas + PIGPIO + I2C + ADS1115 A/D Chip

Post by stevedee » Tuesday 27th April 2021 6:52am

Askjerry wrote:
Monday 26th April 2021 11:26pm
That's not going to work... it has something like READ_ADS(0) to read the port 0... it doesn't get into specifics as to how it does it...
Your Python code (with lines like READ_ADS(0)) will reference libraries. What I am suggesting is that we look at the library code.
This library will probably also be written in Python (or it may be a C library) and should be easy to spot in the list of import declarations.

User avatar
Askjerry
Posts: 24
Joined: Saturday 18th August 2018 9:06pm
Location: Kyle, Texas, USA
Contact:

Re: Gambas + PIGPIO + I2C + ADS1115 A/D Chip

Post by Askjerry » Tuesday 27th April 2021 12:22pm

Thanks,

I will go through my archive SD card (I completely started over with this Raspberry Pi) and I will see if I can find and deconstruct the code.
(That would be nice if I can pull it off.)

But the offer is still out there if someone wants to PM me I'll send an ADS1115 module to you so you can try to figure it out.

Jerry

Post Reply