Average rainfall 2001-2016, global tropics

Map: Average rainfall 2001-2016, global tropics

sketch: AMS 6-band spectral sensor

Thomas Gumbricht bio photo By Thomas Gumbricht

This Arduino sketch is for a GX16 connected Capacitive Soil Moisture probe that signals the result via the analog port (GX16_AN).

/*
 * Initial test program for
 * Adafruit Feather nRF52840 with XSPECLUM01 board.
 *
 * Test:
 * - GX16 analog signal from Capacitive soil moisture
 *
 * 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

#include <Wire.h>                 // Library

#include "Adafruit_AS726x.h"      // Library for the AMS GX16 sensor

//create the ams spectrometer object
Adafruit_AS726x ams;

//buffer to hold raw values
uint16_t amsScan[AS726x_NUM_CHANNELS];

#if defined(USE_TINYUSB)
#include <Adafruit_TinyUSB.h> // for Serial
#endif

bool gx16ams = false;

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


  Serial.begin(115200);

  //begin and make sure we can talk to the sensor
  if(!ams.begin()){
    Serial.println("No AMS sensor connected to external GX16 port.");
    //while(1);
  } else {
    Serial.println("AMS sensor connected to external GX16 port.");
    gx16ams = true;
  }

}

// Set DAC voltage (raw DAC value)
// 12 bit, 0-4095 <=> 0-3.3V
void DAC6571_setVoltage(uint16_t v)
{
  uint16_t vh,vl;

  vh=(v>>8) & 0xff;
  vl=v & 0xff;
  Wire.beginTransmission(DAC6571_ADDR);
  Wire.write(vh); // PD bits =0 (bit 4-5) = Normal operation
  Wire.write(vl);
  Wire.endTransmission();
}

#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

void value_print_SpectraScan(String idStr, int onoff, int start_ch, int end_ch){

  int i;

  Serial.print(idStr);
  Serial.print(onoff);
  Serial.print(',');

  for ( i = start_ch ; i < end_ch ; i++ )
  {
    Serial.print(amsScan[i]);
    if (i < end_ch-1){
      Serial.print(',');
    }

  }

  Serial.print("\n");
}

void gx16spectraScan(bool valueprint=true)
{
  //read the device temperature
  uint8_t temp = ams.readTemperature();

  String idStr = "6-band ams scan:";

  ams.drvOn(); // turn on LED

  ams.startMeasurement(); //begin a measurement

  //wait till data is available
  bool rdy = false;
  while(!rdy){
    delay(5);
    rdy = ams.dataReady();
  }

  ams.readRawValues(amsScan);

  if (valueprint) {

    value_print_SpectraScan(idStr, 1, 0, 6);

  }

  ams.drvOff(); // turn on LED

  ams.startMeasurement(); //begin a measurement

  //wait till data is available
  bool rdy2 = false;
  while(!rdy2){
    delay(5);
    rdy2 = ams.dataReady();
  }

  ams.readRawValues(amsScan);

  if (valueprint) {

    value_print_SpectraScan(idStr, 0, 0, 6);

  }
}

void LED_setVoltage_mV(float vset_mV)
{
  float vdac_mV=600*(RD/RB+1)+(600-vset_mV)*RD/RA;
//  (600.0*(1+RA/RB)-vset_mV)*RD/RA+600.0;
  float r=vdac_mV/DAC_VREF_mV*DAC_MAX;

  DAC6571_setVoltage((uint16_t)r);
}

#define pH_OFFSET_mV 1650
#define pH_GAIN 3
#define pH_mV_PER_pH 59.194
#define pH_OFFSET_pH 7

// in: ADC value (mV)
// Out: pH
float pH_mV_to_pH(float mv)
{
// 0V in => pH=7
// 59.194mV/pH
 float p;

 p= mv-pH_OFFSET_mV;
 p= p/pH_GAIN;
 return (p/pH_mV_PER_pH+pH_OFFSET_pH);
}

float LED_vset_mV = VSET_MIN_mV;

void loop()
{
  bool fullprint = 1;
  bool valueprint = 0;

  float mv_per_lsb = 3600.0F/1024.0F; // 10-bit ADC with 3.6V input range

  int adcvalue = 0;
  float ph,vbat,vid_in,an2;

  float soiLMoisture; //the soil moisture in percent
  uint8_t resultMain;

 delay (200);
 digitalWrite(LED_RED, HIGH);

 if (gx16ams) {

    gx16spectraScan();

 }

 delay (200);
 digitalWrite(LED_RED, LOW);

}