Using an ADS1115 4 channel A to D with Raspberry PI

I used an ads1115 tied to the Pi i2c bus and running at 3.3 volts

I experimented with the Python software but the latest Raspberry Pi OS needs the complexity of a virtual environment for python.

There are several solutions using C code . The simplest I found was

https://github.com/giobauermeister/ads1115-linux-rpi/

I modified ads1115_example.c to save the measured voltages in the ramdisk created in my Pi


This creates the ramdisk at boot time and enables you to not wear out the Pi's memory.

#!/bin/bash

# /home/pi/MakeRAMdisk/setup-ramfs.sh

RAM_DISK="/var/www/html/ramdisk"
RAM_DISK_SIZE=6M

# Create RAM Disk ##########################
if [ ! -z "$RAM_DISK" ]; then
  echo "Creating RAM Disk... $RAM_DISK"
  mkdir -p $RAM_DISK
  chmod 777 $RAM_DISK
  mount -t tmpfs -o size=$RAM_DISK_SIZE tmpts $RAM_DISK/
  echo "RAM Disk created at $RAM_DISK"
fi
############################################
#http://cubik-tech.blogspot.co.uk/2016/03/preserve-your-raspberry-pi-sd-card-with.html

My modified ads1115_example.c

/*

https://github.com/giobauermeister/ads1115-linux-rpi/blob/master/ads1115_example.c
modifeid with thanks by Sunspot to save data to ramdisk

Instructions for compiling and running ads1115_example.c

1 - Clone this repository to your Raspberry Pi

$ git clone  https://github.com/giobauermeister/ads1115-linux-rpi.git
2 - Go into the cloned folder

$ cd /home/pi/ads1115-linux-rpi
3 - Run gcc to compile the example

$ sudo gcc ads1115_example.c ads1115_rpi.c -o ads1115_example
4 - Run the example

$ ./ads1115_example


sudo gcc /home/pi/ads1115-linux-rpi/ads1115_example.c /home/pi/ads1115-linux-rpi/ads1115_rpi.c -o /home/pi/ads1115-linux-rpi/ads1115_example

  /home/pi/ads1115-linux-rpi/ads1115_example

 ============================================================================
 Name        : ads1115_example.c
 Author      : Giovanni Bauermeister
 Description : Read analog values from potentiometer using ADS1115 and prints to terminal
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#include "ads1115_rpi.h"

int main(void) {

    if(openI2CBus("/dev/i2c-1") == -1)
    {
        return EXIT_FAILURE;
    }
    setI2CSlave(0x48);
//    while(1)
//    {
        printf("CH_0 = %.2f V | ", readVoltage(0));
        printf("CH_1 = %.2f V | ", readVoltage(1));
        printf("CH_2 = %.2f V | ", readVoltage(2));
        printf("CH_3 = %.2f V \n", readVoltage(3));
       
       
// ChatGPT gave me the save to file code below!!
       
    FILE *file;
   
    // Open the file in write mode ("w")
    file = fopen("/var/www/html/ramdisk/Volts0.txt", "w");
    if (file == NULL) {
        // Error handling if file cannot be opened
        printf("Could not open file for writing\n");
        return 1;
    }
    // Write the float to the file with desired formatting
    fprintf(file, "%f\n", readVoltage(0));
    // Close the file
    fclose(file);


    // Open the file in write mode ("w")
    file = fopen("/var/www/html/ramdisk/Volts1.txt", "w");
    if (file == NULL) {
        // Error handling if file cannot be opened
        printf("Could not open file for writing\n");
        return 1;
    }
    // Write the float to the file with desired formatting
    fprintf(file, "%f\n", readVoltage(1));
    // Close the file
    fclose(file);
   

    // Open the file in write mode ("w")
    file = fopen("/var/www/html/ramdisk/Volts2.txt", "w");
    if (file == NULL) {
        // Error handling if file cannot be opened
        printf("Could not open file for writing\n");
        return 1;
    }
    // Write the float to the file with desired formatting
    fprintf(file, "%f\n", readVoltage(2));
    // Close the file
    fclose(file);


    // Open the file in write mode ("w")
    file = fopen("/var/www/html/ramdisk/Volts3.txt", "w");
    if (file == NULL) {
        // Error handling if file cannot be opened
        printf("Could not open file for writing\n");
        return 1;
    }
    // Write the float to the file with desired formatting
    fprintf(file, "%f\n", readVoltage(3));
    // Close the file
    fclose(file);


    printf("Float written to file successfully\n");
   
 //   }
   
    return EXIT_SUCCESS;
}

ads1115_rpi.h file for backup

#ifndef ADS1115_RPI
#define ADS1115_RPI

/*=========================================================================
CONFIG REGISTER
-----------------------------------------------------------------------*/
#define CONFIG_REG_OS_SINGLE        (0x8000)
#define CONFIG_REG_OS_BUSY          (0x0000)
#define CONFIG_REG_OS_NOTBUSY       (0x8000)

#define CONFIG_REG_MUX_MASK         (0x7000)
#define CONFIG_REG_MUX_DIFF_0_1        (0x0000) // default
#define CONFIG_REG_MUX_DIFF_0_3        (0x1000)
#define CONFIG_REG_MUX_DIFF_1_3        (0x2000)
#define CONFIG_REG_MUX_DIFF_2_3        (0x3000)
#define CONFIG_REG_MUX_CHAN_0         (0x4000)
#define CONFIG_REG_MUX_CHAN_1         (0x5000)
#define CONFIG_REG_MUX_CHAN_2         (0x6000)
#define CONFIG_REG_MUX_CHAN_3         (0x7000)

#define CONFIG_REG_PGA_6_144V       (0x0000) // +/-6.144V range
#define CONFIG_REG_PGA_4_096V       (0x0200) // +/-4.096V range
#define CONFIG_REG_PGA_2_048V       (0x0400) // +/-2.048V range // default
#define CONFIG_REG_PGA_1_024V       (0x0600) // +/-1.024V range
#define CONFIG_REG_PGA_0_512V       (0x0800) // +/-0.512V range
#define CONFIG_REG_PGA_0_256V       (0x0A00) // +/-0.256V range

#define CONFIG_REG_MODE_CONTIN        (0x0000)
#define CONFIG_REG_MODE_SINGLE        (0x0100) // default

#define CONFIG_REG_DR_8SPS            (0x0000)
#define CONFIG_REG_DR_16SPS            (0x0020)
#define CONFIG_REG_DR_32SPS            (0x0040)
#define CONFIG_REG_DR_64SPS            (0x0060)
#define CONFIG_REG_DR_128SPS        (0x0080) // default
#define CONFIG_REG_DR_250SPS        (0x00A0)
#define CONFIG_REG_DR_475SPS        (0x00C0)
#define CONFIG_REG_DR_860SPS        (0x00E0)

#define CONFIG_REG_CMODE_TRAD        (0x0000) // default
#define CONFIG_REG_CMODE_WINDOW        (0x0010)

#define CONFIG_REG_CPOL_ACTIV_LOW    (0x0000) // default
#define CONFIG_REG_CPOL_ACTIV_HIGH    (0x0080)

#define CONFIG_REG_CLATCH_NONLATCH    (0x0000) // default
#define CONFIG_REG_CLATCH_LATCH        (0x0040)

#define CONFIG_REG_CQUE_1CONV        (0x0000)
#define CONFIG_REG_CQUE_2CONV        (0x0001)
#define CONFIG_REG_CQUE_4CONV        (0x0002)
#define CONFIG_REG_CQUE_NONE        (0x0003) // default

int openI2CBus(char *bus);
int setI2CSlave(unsigned char deviceAddr);

float readVoltage(int channel);


#endif


ads1115_rpi.c file for backup

/*
 * ads1115_rpi.c
 *
 *  Created on: 14 de fev de 2019
 *      Author: giobauermeister
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#include "ads1115_rpi.h"

//char *bus = "/dev/i2c-1";
int i2cFile;
//int deviceAddr = 0x48;
unsigned char writeBuf[3] = {0};

int openI2CBus(char *bus)
{
    if ((i2cFile = open(bus, O_RDWR)) < 0)
    {
        printf("Failed to open the bus. \n");
        return -1;
    } else {
        printf("Bus open \n");
        return 1;
    }
}

int setI2CSlave(unsigned char deviceAddr)
{
    if(ioctl(i2cFile, I2C_SLAVE, deviceAddr) < 0)
    {
        printf("Failed to set I2C_SLAVE at address: 0x%x. \n", deviceAddr);
        return -1;
    } else {
        printf("I2C_SLAVE set at address: 0x%x \n", deviceAddr);
        return 1;
    }

}

float readVoltage(int channel)
{
    unsigned char readBuf[2] = {0};
    unsigned int analogVal;
    float voltage;
    float adnumber;
    unsigned int config = 0;

    config =     CONFIG_REG_OS_SINGLE        |
                CONFIG_REG_PGA_4_096V         |
                CONFIG_REG_MODE_SINGLE         |
                CONFIG_REG_DR_128SPS         |
                CONFIG_REG_CMODE_TRAD         |
                CONFIG_REG_CPOL_ACTIV_LOW     |
                CONFIG_REG_CLATCH_NONLATCH     |
                CONFIG_REG_CQUE_NONE;

    void configDevice(unsigned int config)
    {
        writeBuf[0] = 0x01;
        writeBuf[1] = config >> 8;
        writeBuf[2] = config & 0xFF;
        write(i2cFile, writeBuf, 3);
    }

    switch (channel) {
        case 0:
            config |= CONFIG_REG_MUX_CHAN_0;
            break;
        case 1:
            config |= CONFIG_REG_MUX_CHAN_1;
            break;
        case 2:
            config |= CONFIG_REG_MUX_CHAN_2;
            break;
        case 3:
            config |= CONFIG_REG_MUX_CHAN_3;
            break;
        default:
            printf("Give a channel between 0-3\n");
    }
    configDevice(config);
   
    while (readBuf[0] >> 7 != 1) {
            read(i2cFile, readBuf, 2);
        }
   
    writeBuf[0] = 0x00;
    write(i2cFile, writeBuf, 1);

    if(read(i2cFile, readBuf, 2) != 2) // read data and check error
    {
        printf("Error : Input/Output Error \n");
    }
    else
    {
        analogVal = readBuf[0] << 8 | readBuf[1];
        voltage = (float)analogVal*4.096/32767.0;
    }

    return voltage;
}




I did

pi@office:~ $ cd /home/pi/ads1115-linux-rpi
pi@office:~/ads1115-linux-rpi $ ./ads1115_example

and saw

Bus open
I2C_SLAVE set at address: 0x48
CH_0 = 0.92 V | CH_1 = 0.91 V | CH_2 = 0.91 V | CH_3 = 3.28 V
Float written to file successfully

4 files like Volts0.txt recorded the volts  on inputs 0 1 2 3 at /var/www/html/ramdisk

A browser showed the volts on port 3

http://192.168.1.46/ramdisk/Volts3.txt

3.276600