: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 <COLOR color="#BF0000">&b00000000&</COLOR> as HEX <COLOR color="#BF0000">&H00&</COLOR> and as a plain old <COLOR color="#4000BF">decimal</COLOR>. Same thing.
here is the code… maybe I'm just too close… overlooking a blatant error.
Code
'------------------------------------------------------------------------------------------------- ' 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.
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:
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.
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:
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 (first7-bit I2C address followed by a low R/W bit) – Second byte (points to Config register) – Third byte (MSB of the Config register to be written) – Fourth byte (LSB of the Config register to be written) 2.Write to Address Pointer register: – First byte (first7-bit I2C address followed by a low R/W bit) – Second byte (points to Conversion register) 3.Read Conversion register: – First byte (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
'------------------------------------------------------------------------------------------------- ' 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
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.
I swear this chip is going to drive me crazy… a short drive actually.
…The PDF for the ADS1115:
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:-
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.
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,
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.
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.
Hi… I am attempting to compare the speed of how numerous information tests can i get from ADS1115 between python and C++. So distant i have tried the python utilizing Adafruits library. Now i am searching for a test code in C++ to require a perusing but i might not discover an awfully fundamental one. I have seen that the wiringPi library includes a ads1115.h, but i seem not discover documentation of a test code. Turnkey PCB Assembly - Bittele Electronics
No, there is no documentation on how to use this chip with Gambas and PIGPIO. Once I figure it out, or someone else does and tells me how… I will post the results and code here.
I realize that the PIGPIO can also be used with C and other languages but the calls will remain the same. Does anyone here have code in another language that reads the ADS1115 using PIGPIO? If so, please post your code… I may be able to use what you have to successfully read the chip from within GAMBAS. If not… I may be able to call a routine in another language if needed.
Still no reply… wow… I really want to get this project moving. It looks like my option is to program an Atmel AVR in BASCOM and then read it via SPI… that is sort of Rube Goldberg… and I didn't want to interface one chip with another… because my subscribers are likely not going to have BASCOM, and they will end up using AVRDUDE to program one chip to read another… uggg.
Python has Adifruit routines that work… is it possible to make a call to PYTHON???
I remember in the old TRS-80 days… yeah, I'm freaking old… we could write a BASIC program and put an ASM call to pull an assembly language routine in. Is there a way to pull in the Adifruit and/or Python routine?
I am not really qualified to answer this, as I don't even know what a sADS1115 chip is. However, my thoughts are that any library for Python is probably written in C or C#. If this is the case, then Gambas should be able to access it. The Gambas help for this is here.
With the help of Guido Lutterbach I am about 85% able to get this chip to work. He sent me a python code which works and uses no fancy library to function. ADS1115Runner.py — smartyPies I was able to understand enough of it that I am now getting changing values when I turn the potentiometer.
There is something called Big Endian and Little Endian which basically means that for some reason if you want to send ABCD sometimes you need to send CDAB because of how the Raspberry Pi handles things internally. (It makes no sense to me why this happens… but it does.)
To accomplish this feat, he uses this line of code in Python… value = (value>>8 | value<<8) &=0xFFFF
I found this reference… but I don't understand what it is trying to tell me. https://gambaswiki.org/wiki/comp/gb/stream/byteorder
Can someone here tell me what I need to do to accomplish this in Gambas? (Translate the above into a command or short routine in Gambas.)
He is also doing some sort of 2's complement function to take the returned value and make it into a readable decimal… those are…
LEtoBE
Code
def LEtoBE(c): c = swap2Bytes(c) if(c >= 2**15): c= c-2**16 return c
Eventually I will learn enough python to fully understand this… but for the moment… if someone can translate… that would be freaking awesome.
Guido breaks it all down here… I'm just slowly getting it piece by painful piece. http://smartypies.com/projects/ads1115-with-raspberrypi-and-python/
I did learn that I was using the wrong method to send the configurations… not realizing that the i2cWriteWordData( x , y , z) was NOT asking for the chip address again… I feel so silly now… but instead asking for:
<COLOR color="#0000FF">i2cWriteWordData( Currently Open Bus , REGISTER TO WRITE , WORD TO GET WRITTEN)</COLOR>
So for now, I am going through the datasheet… writing down the BITS to make the CONFIGURATION, then manually swapping the BYTES and putting it into the code.
The numbers coming out are changing… and sometimes gibberish… but at least I know now that I need to post-process before dumping them into a TEXTBOX.
I think I found at least a partial answer… a command called <COLOR color="#0000FF">CShort (Expr AS Variant)</COLOR> getting closer at least… then eventually I'll replace this thread with an exact step-by-step to help out anyone else from going through this!
<COLOR color="#40BF00">AFTER 5 MONTHS I GOT IT!!!!</COLOR>
Code
Public Sub BTN_POLL_ADS_P1_Click() intReply = i2cOpen(1, DEVICE_ADDRESS, 0) If intReply = 0 Then DSP_01.text = "OPEN" Else DSP_01.text = "ERROR" '----------------------------------------------------------------------------- ' For all word values below, they need to be byteswapped due to Big Endian ' Example: &HFF7F (Low Threshold) needs to be sent as &H7FFF& below. '----------------------------------------------------------------------------- ' Reset the ADS1115 intReply = i2cWriteByteData(0, RESET_ADDRESS, RESET_COMMAND) ' Set Low Threshold intReply = i2cWriteWordData(0, POINTER_LOW_THRESHOLD, &H7FFF&) ' Set High Threshold intReply = i2cWriteWordData(0, POINTER_HIGH_THRESHOLD, &H8000&) ' Specify the configuration and start conversion intReply = i2cWriteWordData(0, POINTER_CONFIGURATION, &H8383&) '----------------------------------------------------------------------------- Wait 0.020 '----------------------------------------------------------------------------- ' Pull the raw data from the ADS1115 in native format ADS_RAW = i2cReadWordData(0, POINTER_CONVERSION) '----------------------------------------------------------------------------- 'Swap 2 Bytes ADS_FIXED = (Lsr(ads_raw, 8) Or Lsl(ADS_RAW, 8)) And &Hffff& '----------------------------------------------------------------------------- ' LE to BE If ADS_fixed >= 2 ^ 15 Then ADS_FIXED = ADS_fixed - (2 ^ 16) Endif '----------------------------------------------------------------------------- ' Display the corrected data into the textbox. DSP_03.text = ADS_FIXED '----------------------------------------------------------------------------- ' Close the process so we can read/write to another device. intReply = i2cClose(0) If intReply = 0 Then DSP_02.text = "CLOSED" Else DSP_02.text = "ERROR" End
On a 3.3v setup I am getting readings from 2 to 26,500 which means I'm getting somewhere around 0.000125v accuracy. (Theoretical) Probably way more than I need to read a wind gauge… but hey… IT WORKS!!!!
I wanted to do an update… calculating the HEX numbers to send to the chip has been a pain in the posterior… so I made a helpful spreadsheet to figure them out… it does all the work for you.
For an example, I wanted to configure the chip to use Port 0 to Port 1 in differential mode, then connected Port 1 to ground, and Port 0 to the center tap of a potentiometer… the result was &h8383 as shown in the spreadsheet. You simply fill out the multiple questions in the lower left based on the chart… and it provides the programming number for the configuration. Attachment
Sample GAMBAS QT file
PDF for printing as a desk reference
Then I created a simple demo program with comments to get you started. Let me know if it is helpful to you!
Attachment
Spreadsheet to calculate values
Unzip the above and copy the folder to wherever you keep your GAMBAS projects.