/*
* Initial test program for
* Adafruit Feather nRF52840 with XSPECLUM01 board.
*
* Test:
* - rs485 communication with NPK+pH+SM-EC sensor, ModbusMaster
*
* 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
// Set the baud rate for the sensor connection
// The soil-NPK sensor is set to a baudrate of 4800
Serial1.begin(4800);
node.begin(1, Serial1);
node.preTransmission(PreTransmission);
node.postTransmission(PostTransmission);
}
void print_rs485_modbus_npk(float temperature, float sm, int ec, float ph, int nitrogen, int phosphorus, int potassium, int salinity, int tds){
//temp 34.0, sm 80.2, ph 8.4, N:2, P:51, K: 44107, salinity98, tds: 1539.0
Serial.print(temperature,1);
Serial.print(',');
Serial.print(sm,1);
Serial.print(',');
Serial.print(ph,1);
Serial.print(',');
Serial.print(nitrogen);
Serial.print(',');
Serial.print(phosphorus);
Serial.print(',');
Serial.print(potassium);
Serial.print(',');
Serial.print(salinity);
Serial.print(',');
Serial.print(tds);
Serial.print("\n");
}
void full_print_rs485_modbus_npkphcth(float temperature, float sm, int ec, float ph, int nitrogen, int phosphorus, int potassium, int salinity, int tds){
Serial.print("Temperature: ");
Serial.print(temperature,1);
Serial.print(", SM: ");
Serial.print(sm,1);
Serial.print(", pH: ");
Serial.print(ph,1);
Serial.print(", N: ");
Serial.print(nitrogen);
Serial.print(", P: ");
Serial.print(phosphorus);
Serial.print(", K: ");
Serial.print(potassium);
Serial.print(", salinity: ");
Serial.print(salinity);
Serial.print(", TDS: ");
Serial.print(tds);
Serial.print("\n");
}
void rs485_modbus_npkphcth(){
uint8_t resultMain;
float sm = -999.0;
float temperature = -999.0;
int ec = -999;
float ph = -999;
int nitrogen = -999;
int phosphorus = -999;
int potassium = -999;
int salinity = -999;
int tds = -999;
// 0x0000 = Moisture (%)
delay (500);
resultMain = node.readInputRegisters(0x000, 1);
if (resultMain == node.ku8MBSuccess)
{
sm = float( node.getResponseBuffer(0x00) )/10;
}
// 0x0001 = Temperature (C)
delay (500);
resultMain = node.readInputRegisters(0x0001, 1);
if (resultMain == node.ku8MBSuccess)
{
temperature = float( node.getResponseBuffer(0x00) )/10;
}
// 0x0002 = ec (uS/cm)
delay (500);
resultMain = node.readInputRegisters(0x0002, 1);
if (resultMain == node.ku8MBSuccess)
{
ec = float( node.getResponseBuffer(0x00) )/10;
}
// 0x0003 = ph
delay (500);
resultMain = node.readInputRegisters(0x0003, 1);
if (resultMain == node.ku8MBSuccess)
{
ph = float( node.getResponseBuffer(0x00) )/10;
}
// 0x0004 = phosphorus (mg/kg)
delay (500);
resultMain = node.readInputRegisters(0x0004, 1);
if (resultMain == node.ku8MBSuccess)
{
phosphorus = node.getResponseBuffer(0x00);
}
// 0x0005 = potassium (mg/kg)
delay (500);
resultMain = node.readInputRegisters(0x0005, 1);
if (resultMain == node.ku8MBSuccess)
{
potassium = node.getResponseBuffer(0x00);
}
// 0x0006 = nitrogen
delay (500);
resultMain = node.readInputRegisters(0x0006, 1);
if (resultMain == node.ku8MBSuccess)
{
nitrogen = node.getResponseBuffer(0x00);
}
// 0x0007 = salinity (ppm)
delay (500);
resultMain = node.readInputRegisters(0x0007, 1);
if (resultMain == node.ku8MBSuccess)
{
salinity = node.getResponseBuffer(0x00);
}
// 0x0008 = tds (ppm)
delay (500);
resultMain = node.readInputRegisters(0x0008, 1);
if (resultMain == node.ku8MBSuccess)
{
tds = node.getResponseBuffer(0x00);
}
full_print_rs485_modbus_npkphcth(temperature, sm, ec, ph, nitrogen, phosphorus, potassium, salinity, tds);
}
#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()
{
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_npkphcth();
delay (100);
digitalWrite(LED_RED, LOW);
}
Map: Average rainfall 2001-2016, global tropics