/*
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] = ' ';
------------------------- 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);
}
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();
}