/*
* Initial test program for
* Adafruit Feather nRF52840 with XSPECLUM01 board.
*
* RS485/MODBUS:
* - rs485 communication with temp+sm+ec sensor
*
* Note: the feather needs to be removed from the board when updated,
* since the bootloader does not set nKILL high (which will turn off the device after a few hundreds of ms).
*
*
* Arduino IDE installation:
* ========================
* Download and install the Arduino IDE (At least v1.8)
* Start the Arduino IDE
* Go into Preferences
* Add https://adafruit.github.io/arduino-board-index/package_adafruit_index.json as an 'Additional Board Manager URL'
* Restart the Arduino IDE
*
* Open the Boards Manager option from the Tools -> Board menu and install 'Adafruit nRF52 by Adafruit'
* Once the BSP is installed (takes long time with a long delay in the middle), select
* Adafruit Bluefruit nRF52840 Feather Express (for the nRF52840) from the Tools -> Board menu
*
*
*
* To update the bootloader:
* =========================
* Step 1:
* Tools -> Board: Adafruit Feather nRF52840 Express
* select "Bootloader DFU for Bluefruit nRF52" for Tools->Programmer
* Select the right com port
* Tools->Burn Bootloader
*
* Step 2:
* Double-click the Reset button. NeoPixel turns green.
* Drag the downloaded .uf2 file to FTHR840BOOT. The LED will flash.
*
*/
#define DAC6571_ADDR 0x4C
#define BNC A0
#define SPECTRO_AN A1 // The analog video signal for the spectrometer
#define GX16_AN A2 // The GX16 analog sensor signal
#define nKILL 17
#define nPBINT 18
#define ONEWIRE 19
#define GPIOSCK 26 // NC
#define nRE 25
#define GPIOMISO 24
#define GPIORX 1
#define GPIOTX 0
#define GPIOD2 2
#define SPECTRO_CLK 13
#define SPECTRO_ST 12
#define SPECTRO_TRG 11
#define SPECTRO_EOS 10
#define SPECTRO_BOOST_EN 9
#define LED_BUCK_EN 6
#define LED_PULSE 5
#define GPIOSCL 23
#define GPIOSDA 22
#define USERSWITCH 7
#define BATTERYV2 A6
#define NEOPIXEL 8
#define SPECTRO_CHANNELS 256 // Nr of spectral channels in sensor
#define SPECTRO_START_CHANNEL 64 // First channel with valid data
#define SPECTRO_END_CHANNEL 256 // Last channel with valid data
#define SPECTRO_integration_time 300 // Integration time for spectral sensor sampling ("expsoture rime")
uint16_t data[SPECTRO_CHANNELS];
#include <Adafruit_NeoPixel.h> // Library that provides NeoPixel functions
// -- Create a NeoPixel object called onePixel that addresses 1 pixel in pin 8
Adafruit_NeoPixel rgbPixel = Adafruit_NeoPixel(1, 8, NEO_GRB + NEO_KHZ800);
#include <Wire.h> // Library
#include "SHT2x.h" // Library for in-box temperature and relaive humidity
// -- Create a SHT2x object called sht for accessing the in-box Temperature and Relative Humidity
SHT2x sht;
/* ModbusMaster For communication with RS485+MODBUS sensors */
#include <ModbusMaster.h>
/* tinyusb is for the serical connection with Adafruit nRF52 boards */
#if defined(USE_TINYUSB)
#include <Adafruit_TinyUSB.h> // for Serial
#endif
/* Setup the Modbus transmission basics */
void PreTransmission(){
// Set transmit mode
digitalWrite(nRE, HIGH);
}
void PostTransmission(){
// Set receive mode
digitalWrite(nRE, LOW);
}
// instantiate ModbusMaster object
ModbusMaster node;
/* END - Setup the Modbus transmission basics */
void setup() {
pinMode(BNC, INPUT); // BNc connection - usually an Ion Selecteve Electrode (ISE)
pinMode(SPECTRO_AN, INPUT); // Spectro video analog signal
pinMode(GX16_AN, INPUT); // Aalog signal from GX16 expansion socket)
pinMode(nKILL, OUTPUT); // #KILL
pinMode(nPBINT, INPUT); // #PBINT (pushbutton)
pinMode(ONEWIRE, INPUT); // 1W interface (pulled up to 3v3 by 2k2)
pinMode(SCK, OUTPUT); // - (not connected)
pinMode(nRE, OUTPUT); // #RE (Receive enabled, RS485)
pinMode(GPIOMISO, OUTPUT); // - (not connected)
pinMode(GPIORX, INPUT); // Rx (Uart)
pinMode(GPIOTX, OUTPUT); // Tx (Uart)
pinMode(GPIOD2, OUTPUT); // - (not connected)
pinMode(SPECTRO_CLK, OUTPUT); // Spectrometer clock pulse
pinMode(SPECTRO_ST, OUTPUT); // Spectrometer start pulse
pinMode(SPECTRO_TRG, INPUT); // Spectrometer trigger pulse
pinMode(SPECTRO_EOS, INPUT); // SPECTRO_EOS
pinMode(SPECTRO_BOOST_EN, OUTPUT); // Spectrometer end of scan
pinMode(LED_BUCK_EN, OUTPUT); // LED_BUCK_EN
pinMode(LED_PULSE, OUTPUT); // LED_PULSE
pinMode(GPIOSCL, INPUT); // SCL
pinMode(GPIOSDA, INPUT); // SDA
pinMode(USERSWITCH, INPUT); // User switch
pinMode(A6, INPUT); // Battery voltage/2
pinMode(LED_BUILTIN, OUTPUT); // Red LED
pinMode(NEOPIXEL, OUTPUT); // RGB
// Disable LED driver
digitalWrite(LED_BUCK_EN, LOW);
digitalWrite(LED_PULSE, HIGH);
// Start Spectrometer and RS485
digitalWrite(SPECTRO_BOOST_EN, HIGH); // +5V for rs485
digitalWrite(nRE, HIGH); // Set transmit mode
Serial1.begin(9600);
node.begin(1, Serial1);
node.preTransmission(PreTransmission);
node.postTransmission(PostTransmission);
}
void full_print_rs485_modbus_temp_sm_ec(int temperature, int sm, int ec, int salinity, int tds, int epsilon){
Serial.print("rs485/modbus temp-sm-ec-sal-tds-e:");
Serial.print("temperature= ");
Serial.print(temperature);
Serial.print("'C\t moisture= ");
Serial.print(sm);
Serial.print("'%\t EC= ");
Serial.print(ec);
Serial.print("'uS/cm\t salinity= ");
Serial.print(salinity);
Serial.print("'mg/kg\t tds= ");
Serial.print(tds);
Serial.print("'mg/kg\t epsilon= ");
Serial.print(epsilon);
Serial.print("(unitless)\n");
}
void print_rs485_modbus_temp_sm_ec(int temperature, int sm, int ec, int salinity, int tds, int epsilon){
Serial.print("rs485/modbus temp-sm-ec-salinity-tds-epsilon:");
Serial.print(temperature);
Serial.print(',');
Serial.print(sm);
Serial.print(',');
Serial.print(ec);
Serial.print(',');
Serial.print(salinity);
Serial.print(',');
Serial.print(tds);
Serial.print(',');
Serial.print(epsilon);
Serial.print("\n");
}
void rs485_modbus_temp_sm_ec(bool fullprint=0, bool valueprint=1){
uint8_t resultMain;
int temperature = -999;
int sm = -999;
int ec = -999;
int salinity = -999;
int tds = -999;
int epsilon = -999;
// 0x0000 = temperature (Celsius * 100)
delay (50);
resultMain = node.readInputRegisters(0x0000, 1);
if (resultMain == node.ku8MBSuccess)
{
temperature = node.getResponseBuffer(0x00);
}
// 0x0001 = soil moisture (vol/vol)
delay (50);
resultMain = node.readInputRegisters(0x0001, 1);
if (resultMain == node.ku8MBSuccess)
{
sm = node.getResponseBuffer(0x00);
}
// 0x0002 = electrical conductivity (mg/L)
delay (50);
resultMain = node.readInputRegisters(0x0002, 1);
if (resultMain == node.ku8MBSuccess)
{
ec = node.getResponseBuffer(0x00);
}
// 0x0003 = Salinity (mg/L)
delay (50);
resultMain = node.readInputRegisters(0x0003, 1);
if (resultMain == node.ku8MBSuccess)
{
salinity = node.getResponseBuffer(0x00);
}
// 0x0004 = TDS
resultMain = node.readInputRegisters(0x0004, 1);
if (resultMain == node.ku8MBSuccess)
{
tds = node.getResponseBuffer(0x00);
}
// 0x0005 = Epsilon (Dielectric constant)
resultMain = node.readInputRegisters(0x0005, 1);
if (resultMain == node.ku8MBSuccess)
{
epsilon = node.getResponseBuffer(0x00);
}
if (fullprint){
full_print_rs485_modbus_temp_sm_ec(temperature, sm, ec, salinity, tds, epsilon);
}
else if (valueprint) {
print_rs485_modbus_temp_sm_ec(temperature, sm, ec, salinity, tds, epsilon);
}
}
#define RA 68.0
#define RB 16.9
#define RD 75.0
#define DAC_VREF_mV 3300.0
#define DAC_MAX 4095.0
#define VSET_MIN_mV 566
#define VSET_MAX_mV 3558
#define pH_OFFSET_mV 1650
#define pH_GAIN 3
#define pH_mV_PER_pH 59.194
#define pH_OFFSET_pH 7
void loop()
{
bool fullprint = 1;
bool valueprint = 0;
int adcvalue = 0;
float ph,vbat,vid_in,an2;
float mv_per_lsb = 3600.0F/1024.0F; // 10-bit ADC with 3.6V input range
delay (100);
digitalWrite(LED_RED, HIGH);
rs485_modbus_temp_sm_ec(fullprint,valueprint);
delay (100);
digitalWrite(LED_RED, LOW);
}
Map: Average rainfall 2001-2016, global tropics