I have two programs, one for a modbus master and the other to read the TI ADS1118 ADC each one works as expected. I combined the programs together into a single program and the ADC part seems to fail on SPI but, again independently they both work fine. I added debugging serial prints and it fails on getting temperature from the ADC. By fails I mean it seems to just stop. Can someone explain how combining could interrupt the SPI functioning (if that is what the problem really is) and help me to get it to work?
Program Libs are ADS1118 https://github.com/denkitronik/ADS1118 modified to work with Teensy and ModbusMaster https://github.com/4-20ma/ModbusMaster.
Here is my combined version of the program:
Modbus_coriolis_for_Flow_71_and_72_copy_202_copy_20250110115817.ino
In a separate tab, ReadRegistersFunction.ino for reading the Modbus sensor,
SharedDefinitions.h
Any help is appreciated!
Program Libs are ADS1118 https://github.com/denkitronik/ADS1118 modified to work with Teensy and ModbusMaster https://github.com/4-20ma/ModbusMaster.
Here is my combined version of the program:
Modbus_coriolis_for_Flow_71_and_72_copy_202_copy_20250110115817.ino
Code:
//Modbus_coriolis_for_Flow_71_and_72_copy_202_copy_20250110115817.ino
#include <ModbusMaster.h>
#include "SharedDefinitions.h" // Shared structures and constants
#include "ADS1118.h"
#include <SPI.h>
// Define the chip select pin for the ADS1118
#define CS 10
// Create an ADS1118 object
ADS1118 ads1118(CS);
// Instantiate ModbusMaster object
ModbusMaster node;
// Constants for configuration
const uint8_t SLAVE_ID_71 = 71;
const uint8_t SLAVE_ID_72 = 72;
const bool USE_SLAVE_72 = false;
const uint8_t MAX_RETRIES = 3; // Max retries for failed reads
const uint16_t PRE_POST_DELAY = 500; // Delay in microseconds
// Addresses to read
const uint16_t ADDRESSES[] = {0x00F6, 0x0102, 0x00FC, 0x0104, 0x00F8, 0x0122, 0x00FA, 0x01C6, 0x01C8};
const size_t NUM_ADDRESSES = sizeof(ADDRESSES) / sizeof(ADDRESSES[0]);
// Structures for storing results
ModbusResults results71, results72;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
while(!Serial);
Serial2.begin(9600);
Serial.println("in setup");
node.begin(SLAVE_ID_71, Serial2); // Initialize ModbusMaster with Slave ID 71
// Set pre/post transmission delays
node.preTransmission([]() {
delayMicroseconds(PRE_POST_DELAY);
});
node.postTransmission([]() {
delayMicroseconds(PRE_POST_DELAY);
});
Serial.println("end setup");
}
void loop() {
Serial.println("enter loop");
float pressures[4];
float temperature;
// Read pressures and temperature from the ADS1118
//Serial.println("Reading pressures and temperature...");
readPressuresAndTemperature(pressures, temperature);
Serial.println("exit analog get function");
// Display the temperature
Serial.print("Temperature: ");
Serial.print(temperature, 1); // Display with 1 decimal place
Serial.println(" F");
// Display the pressure readings
for (int i = 0; i < 4; i++) {
Serial.print("Pressure ");
Serial.print(i + 1);
Serial.print(": ");
Serial.println(pressures[i], 2); // Display with 2 decimal places
}
Serial.println(); // Add a blank line between readings
//////////////////////////////////////////////
Serial.println("Reading values for slave ID 71:");
readModbusSlave(SLAVE_ID_71, results71);
if (USE_SLAVE_72) {
Serial.println("Reading values for slave ID 72:");
readModbusSlave(SLAVE_ID_72, results72);
}
//toggleLED();
}
// Function to read values from a Modbus slave
void readModbusSlave(uint8_t slaveID, ModbusResults &results) {
node.begin(slaveID, Serial2);
for (size_t i = 0; i < NUM_ADDRESSES; i++) {
results.values[i] = readFloatRegister(ADDRESSES[i], MAX_RETRIES);
}
Serial.println("End of reading.\n");
}
// Function to read a 4-byte float from a Modbus register
float readFloatRegister(uint16_t address, uint8_t retries) {
for (uint8_t attempt = 0; attempt < retries; attempt++) {
ReadResult readResult = readInputRegistersAsFloat(address, 2, ENDIAN_BIG);
if (readResult.result == node.ku8MBSuccess) {
Serial.print("Address ");
Serial.print(address, HEX);
Serial.print(": ");
Serial.println(readResult.value, 4);
return readResult.value;
} else {
Serial.print("Failed to read address ");
Serial.print(address, HEX);
Serial.print(" (Attempt ");
Serial.print(attempt + 1);
Serial.println(")");
}
delay(10); // Short delay before retry
}
Serial.print("Address ");
Serial.print(address, HEX);
Serial.println(": Failed after max retries.");
return 0.0; // Return default value on failure
}
// Function to toggle the LED for visual feedback
void toggleLED() {
//digitalWrite(LED_BUILTIN, HIGH);
delay(250);
//digitalWrite(LED_BUILTIN, LOW);
delay(250);
}
In a separate tab, ReadRegistersFunction.ino for reading the Modbus sensor,
Code:
//ReadRegistersFunction.ino for Modbus_coriolis_for_Flow_71_and_72
#include <ModbusMaster.h>
#include "SharedDefinitions.h" // Include shared definitions
// Extern declaration for node
extern ModbusMaster node;
//
// Function to read input registers and return the value as a float
ReadResult readInputRegistersAsFloat(uint16_t startAddress, uint16_t numRegisters, Endianness endianness) {
auto hextoFloat = [](byte hexBytes[]) -> float {
union {
byte b[4];
float floating;
} dataHex;
dataHex.b[0] = hexBytes[1];
dataHex.b[1] = hexBytes[0];
dataHex.b[2] = hexBytes[3];
dataHex.b[3] = hexBytes[2];
return dataHex.floating;
};
uint8_t result;
uint16_t data[numRegisters];
ReadResult readResult;
result = node.readInputRegisters(startAddress, numRegisters);
if (result == node.ku8MBSuccess) {
for (uint8_t i = 0; i < numRegisters; i++) {
data[i] = node.getResponseBuffer(i);
}
byte hexBytes[4];
hexBytes[0] = (data[0] >> 8) & 0xFF;
hexBytes[1] = (data[0]) & 0xFF;
hexBytes[2] = (data[1] >> 8) & 0xFF;
hexBytes[3] = (data[1]) & 0xFF;
readResult.value = hextoFloat(hexBytes);
} else {
readResult.value = 0.0; // Default value on error
}
readResult.result = result;
return readResult;
}
SharedDefinitions.h
Code:
//SharedDefinations.h for Modbus_coriolis_for_Flow_71_and_72
#ifndef SHARED_DEFINITIONS_H
#define SHARED_DEFINITIONS_H
// Enum for byte order
enum Endianness {
ENDIAN_BIG,
ENDIAN_LITTLE
};
// Structure for read result
struct ReadResult {
float value;
uint8_t result;
};
// Structure for storing Modbus results
struct ModbusResults {
float values[9];
};
#endif // SHARED_DEFINITIONS_H
Code:
// Function to read pressures and temperature from the ADS1118
void readPressuresAndTemperature(float pressures[4], float &temperature) {
Serial.println("begin analog read functions");
float mV, mA;
//
ads1118.setSamplingRate(ads1118.RATE_64SPS);
ads1118.setFullScaleRange(ads1118.FSR_2048);
Serial.println("Set ADS1118 configuration smple and scale");
// Read the temperature (in Celsius)
Serial.println(String(ads1118.getTemperature(),6)+" C"); //Getting temperature
float tempC = ads1118.getTemperature();
Serial.print( tempC);
temperature = tempC * 9.0 / 5.0 + 32.0; // Convert to Fahrenheit
Serial.print("get temp ");
Serial.println(temperature);
for (int i = 0; i < 4; i++) {
// Map the loop index to the correct ADS1118 input channels
int channel;
switch (i) {
case 0: channel = ads1118.AIN_0; break;
case 1: channel = ads1118.AIN_1; break;
case 2: channel = ads1118.AIN_2; break;
case 3: channel = ads1118.AIN_3; break;
}
// Select the input channel and allow settling time
ads1118.setInputSelected(channel);
delayMicroseconds(50); // Allow settling time
// Discard the first reading and take the second
ads1118.getMilliVolts(); // Discard first reading
mV = ads1118.getMilliVolts(); // Read stabilized value
// Calculate current (mA) based on calibration values
switch (i) {
case 0: mA = mV * 0.011774056 - 0.0706443 + 0.07; break;
case 1: mA = mV * 0.011816083 - 0.000708965; break;
case 2: mA = mV * 0.011794713 - 0.002240995; break;
case 3: mA = mV * 0.011810675 - 0.002244028; break;
}
// Calculate pressure
pressures[i] = mA * 250 - 1000.0;
if (i == 0) pressures[i] -= 0.32; // Adjustment for Pressure 1
if (i == 1) pressures[i] -= 0.12; // Adjustment for Pressure 2
if (pressures[i] < 0) pressures[i] = 0.0; // Prevent negative pressure
}
}
Any help is appreciated!