@boots33 Sure... It's not finished in that want to reverse some of the mods made in desperate attempts to isolate the problem, before realising the illogic of the range checking.
It's no different to any other pulse timer in function, and doubtless could be made more efficient by more knowledgeable people than I, but it is working flawlessly now which was the objective.
The original idea was that the Slave would sleep as per Gammon's I2C example, constantly available to be remote commanded, but as the switched off ADC stayed off after sleep I lost the battery reading which divider was running continually. Inserting a latching relay, it ended up remote powered up with the readings taken during setup, otherwise it is completely off.
It's a straight 5v promini chinese clone with only the power led removed, powered by 4x2AA cells via a latching signal relay, as it is only fired up every hour by the sleeping Master, it should hopefully last a while...
Might extend the cycles to 3 or 4 hours, but for now it is feeding back accurate information on groundwater intrusion which has proven a bit of a surprise...
// Adapted from Nick Gammon tutorials from 18th February 2011
//ADC disabling prior to sleep failed to restart originally and written out
#include <Wire.h>
#include <avr/sleep.h>
const byte MY_ADDRESS = 61;
const byte AWAKE_LED = 13;
#define echoPin 5
#define trigPin 6
#define USon 4
#define BatteryIn A3
long duration;
int distance,test,test2;
const unsigned long WAIT_TIME = 500;
volatile unsigned long counter;
volatile int ultradepth, batterypower;
// various commands we might get
enum {
CMD_READ_TANK = 2,
CMD_READ_BATTERY = 3
};
char command;
void setup()
{
command = 0;
pinMode(USon, OUTPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
analogReference(INTERNAL);
digitalWrite(USon,LOW);
digitalWrite(USon, HIGH);
delay(100);
digitalWrite(trigPin,HIGH);
delay (100);
digitalWrite(trigPin,LOW);
delay(100);/// Allow decay of pulse
READULTRASONIC();
READPOWER();
Wire.begin (MY_ADDRESS);
Wire.onReceive (receiveEvent); // interrupt handler for incoming messages
Wire.onRequest (requestEvent); // interrupt handler for when data is wanted
delay(150);
} // end of setup
void receiveEvent (int howMany)
{
command = Wire.read (); // remember command for when we get request
} // end of receiveEvent
void loop (){
if (++counter >= WAIT_TIME)
{
flasher();//1 flash signals going to sleep
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_enable();
digitalWrite (AWAKE_LED, LOW);
sleep_cpu ();
sleep_disable();
// release TWI bus
TWCR = bit(TWEN) | bit(TWIE) | bit(TWEA) | bit(TWINT);
for (byte i = 0; i < 3; i++)
{//3 flashes wakened up
flasher();
};
// turn it back on again
Wire.begin (MY_ADDRESS);
}
}
void READULTRASONIC(){//JSN-SR04-2.0
digitalWrite(USon,HIGH);
delay(100);
duration=0;
distance=0;
test=1;
test2=3;
while ((test!=test2)&&((distance<300)||(distance>1860))){// Get two consecutive readings in specified range
digitalWrite(trigPin, LOW);
delayMicroseconds(100);
digitalWrite(trigPin, HIGH);
delayMicroseconds(150);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = duration/5.82;//This is in mm
if (test!=distance){
test=distance;
distance=0;
}
else{
test2=distance;
}
delay(100);///// 500 originally but why???????
}
digitalWrite(USon,LOW);
ultradepth=distance;
}
void READTANK (){
byte buf [2];
buf [0] = ultradepth >> 8;
buf [1] = ultradepth & 0xFF;
Wire.write (buf, 2);
}/// end of READTANK
void READPOWER(){//Still needs cap on resistive divider
int val, read1, read2;
read1=1;
read2=2;
///Get two consecutive identical readings
while(read1!=read2){
val= analogRead(BatteryIn);
if(read1!=val){
read1=val;
}
else{
read2=val;
}
}
batterypower=val;
}
void READBATTERY ()
{// Battery reading send now
byte buf [2];
buf [0] = batterypower >> 8;
buf [1] = batterypower & 0xFF;
Wire.write (buf, 2);
} // end of READBATTERY
void requestEvent ()
{// Original which parameter removed
switch (command) {
case CMD_READ_TANK: READTANK (); break; // send Tank Depth Reading
case CMD_READ_BATTERY: READBATTERY (); break; // send Drone battery reading
} // end of switch
} // end of requestEvent
void flasher(){
digitalWrite (AWAKE_LED, HIGH);
delay (20);
digitalWrite (AWAKE_LED, LOW);
delay (50);
}
EDIT - With playing around with so many variations, I had copied the wrong sketch version here, now resolved.
One of the more frustrating aspects I found in this setup was instability, presumably due to Wire interrupts or a dodgy connection somewhere. The Slave would in isolation get a valid figure to forward, yet somehow the Master would pass completely different figures to the Gateway or everything would lock up.
One curiosity noted was the delay between the Master powering up the Slave and requesting results over Wire, it worked fine with sleep(5000), but 1000 would introduce instability.