Solar Sensor Arduino Sketch

Definitions and Variables

/*

   SolarSensor-replacement for the Solar Transmitter.

   No built-in solar panel. uses the patio roof mounted panel - good for 120MA@up to 18V

   Arduino ProMini 3.3V 8MHz

   John Saunders 3/30/2021 4 digit for MAH

*/


// For analogs:

#define CP A0                   //Charger voltage divide by 6.023

#define BP A1                   //Battery Voltage via divider 2.003

#define IP A2                   //Voltage measuring current through 5.6 ohm shunt, 179 MA/V

#define RP A3                   //Voltage across LM385 1.233 Volt reference diode


// For the message transmission

// For the front porch of the transmission:

#define PULSE_PORT 2

// Transmit pulse lengths

#define PREPULSE_LEN 20

#define SETUP_LEN 10


// For the environmental sensor

#include <SPI.h>

#include <Adafruit_Sensor.h>

#include <Adafruit_BME280.h>


#define BME_SCK 13

#define BME_MISO 12

#define BME_MOSI 11

#define BME_CS 10


#define SEALEVELPRESSURE_HPA (1013.25)          // Used at 0 feet ASL

Adafruit_BME280 bme(BME_CS); // hardware SPI


// ---------------------- Analog processing ---------------

int rawAnalog;

float voltVal;      // For floating-point calculations

float Vcc;          // 3.3V supply is also the analog reference

float dMah;         // daily milliamp-hours

int accChg;         // To average the solar current

float pMah;         // Previous mah

int loopCount;      // Finds the middle of the night to swap the MAH values


// This buffer used alternately for boyh the r and the s massages

char txBuf[34] = {"14L1776r,M,012,345,2678,1901,abnl"};


// Need to be sure of the field length, no leading zero blank or decimal points

void convert(int mult, int index) {

  int rem, charVal;

  int decVal;

  voltVal *= mult;

  decVal = int(voltVal);

  if (index > 18 && txBuf[7] == 'r') {

    charVal = decVal / 1000 + 48;

    txBuf[index++] = char(charVal);

    rem = decVal % 1000;

    decVal = rem;

  }

  charVal = decVal / 100 + 48;

  txBuf[index++] = char(charVal);

  rem = decVal % 100;

  charVal = rem / 10 + 48;

  txBuf[index++] = char(charVal);

  charVal = rem % 10 + 48;

  txBuf[index++] = char(charVal);

  txBuf[index++] = ',';

  txBuf[index++] = ' ';

  txBuf[index] = ' ';

Functions

 ------------------------- Transmitting the messages ------------


void transmit(void) {

  byte cksum = 0;

  byte chk;

  for (int ix = 11; ix < 28; ix++) {      // Calculate the checksum modulo 256

    cksum += txBuf[ix];

  }

  chk = cksum / 16;                       // ... and add to the end of the message as 2 Hex

  if (chk < 10) {

    txBuf[29] = chk + '0';

  }

  else {

    txBuf[29] = chk + '7';

  }

  chk = cksum & 0x0F;

  if (chk < 10) {

    txBuf[30] = chk + '0';

  }

  else {

    txBuf[30] = chk + '7';

  }

  txBuf[31] = 0x0d;

  txBuf[32] = 0x0a;

  digitalWrite(PULSE_PORT, HIGH);           // To generate an interrupt in the receiver

  delay(PREPULSE_LEN);

  digitalWrite(PULSE_PORT, LOW);

  delay(SETUP_LEN);

  Serial.write(txBuf, 33);

}


// --------------- Calculate the fields and store in the transmit buffer ------


void storeSmessage(void) {

  // s message fields: Temperature deg F, Humidity %, Solar Current MA, Battery Volts in tenths

  voltVal = bme.readTemperature();

  voltVal = (voltVal * 9 / 5) + 32;               // Convert deg C to deg F

  convert(1, 11);

  voltVal = bme.readHumidity();

  convert(1, 15);

  rawAnalog = accChg / 12;

  voltVal = 179.0F * (1.224F - (Vcc * rawAnalog / 1024));   // solar current through 5.6 ohms

  if (voltVal < 0.0F) {

    voltVal = 0.0F;

  }

  accChg = 0;

  dMah += voltVal;

  if (voltVal > 4) {            // Measuring only the night

    loopCount = 0;

  }

  if (loopCount == 250) {        // About 1 AM

    pMah = dMah;

    dMah = 0;

  }

  convert(1, 19);

  rawAnalog = analogRead(BP);

  voltVal = 2.003F * Vcc * rawAnalog / 1024l;              // Battery voltage

  convert(100, 23);

}


// r message fields: pressure,charging volts,daily MAH, previous MAH

void storeRmessage(void) {

  voltVal = bme.readPressure() / 100;           // In hundreds of Hpa

  voltVal = bme.seaLevelForAltitude(84.0F, voltVal);

  voltVal /= 33.86;                          // To inches of Mercury

  if (voltVal >= 30.00F) {

    voltVal -= 30.00;

  }

  else {

    voltVal -= 20.00;

  }

  convert(100, 11);

  rawAnalog = analogRead(CP);

  voltVal = 6.023F * Vcc * rawAnalog / 1024;  // charging voltage

  convert(10, 15);

  voltVal = dMah / 50;                       // 100 samples per hour

  convert(1, 19);

  voltVal = pMah / 50;

  convert(1, 24);

}

Setup and Loop

void setup() {

  Serial.begin(2400);

  bme.begin();

  dMah = 0;

  pMah = 0;

  accChg = 0;

  loopCount = 0;

}


void loop() {

  loopCount++;

  rawAnalog = analogRead(RP);

  Vcc = 1024 * 1.233F / rawAnalog;        // Supply voltage is calculated

  for (int i = 0; i < 6; i++) {

    rawAnalog = analogRead(IP);

    accChg += rawAnalog;

    delay(5985);

  }

  txBuf[7] = 'r';

  storeRmessage();

  transmit();

  for (int i = 0; i < 6; i++) {

    rawAnalog = analogRead(IP);

    accChg += rawAnalog;

    delay(5986);

  }

  txBuf[7] = 's';

  storeSmessage();

  transmit();

}