Hi folks,
I’m not a programmer and don’t have a lot of experience. So my problem is probably easy to solve, I just can’t see it.
I took the Maker Tutorial Temp sensor code from Maker Tutorial #4 and pasted it into a function. I then put that function into a sketch that wakes and publishes when the accellerometer moves. I got the accellerometer code from here.The code is below.
I don’t know why the temperature only publishes every other time the Photon awakes. Any ideas?
// This #include statement was automatically added by the Particle IDE.
#include <ADXL362DMA.h>
// This #include statement was automatically added by the Particle IDE.
#include <OneWire.h>
// This #include statement was automatically added by the Particle IDE.
#include <PowerShield.h>
SYSTEM_THREAD(ENABLED);
ADXL362DMA accel(SPI, A2);
PowerShield batteryMonitor;
const int ACCEL_INT_PIN = D2;
const char *eventName = "accel";
// Various timing constants
const unsigned long MAX_TIME_TO_PUBLISH_MS = 30000; // Only stay awake for 30 seconds trying to connect to the cloud and publish
const unsigned long TIME_AFTER_PUBLISH_MS = 10000; // After publish, wait 10 seconds for data to go out
const unsigned long TIME_AFTER_BOOT_MS = 20000; // At boot, wait 20 seconds before going to sleep again
const unsigned long TIME_PUBLISH_BATTERY_SEC = 4 * 60 * 60; // every 4 hours, send a battery update
// Stuff for the finite state machine
enum State { RESET_STATE, RESET_WAIT_STATE, PUBLISH_STATE, SLEEP_STATE, SLEEP_WAIT_STATE, BOOT_WAIT_STATE };
State state = RESET_STATE;
unsigned long stateTime = 0;
int awake = 0;
OneWire ds = OneWire(D4); // 1-wire signal on pin D4
unsigned long lastUpdate = 0;
float lastTemp;
//-----------------------------------------
//----------------------------------------------
void setup() {
batteryMonitor.begin();
batteryMonitor.quickStart();
Serial.begin(9600);
}
void loop(void)
{
uint8_t status;
switch(state) {
case RESET_STATE:
Serial.println("resetting accelerometer");
accel.softReset();
state = RESET_WAIT_STATE;
break;
case RESET_WAIT_STATE:
status = accel.readStatus();
if (status != 0) {
// Reset complete
// Set accelerometer parameters
// uint8_t range, bool halfBW, bool extSample, uint8_t odr
// Set sample rate to 50 samples per second
accel.writeFilterControl(accel.RANGE_2G, false, false, accel.ODR_50);
// Set activity and inactivity thresholds, change these to make the sensor more or less sensitive
accel.writeActivityThreshold(250);
accel.writeInactivityThreshold(150);
// Activity timer is not used because when inactive we go into sleep mode; it automatically wakes after 1 sample
// Set inactivity timer to 250 or 5 seconds at 50 samples/sec
accel.writeInactivityTime(250);
// Enable loop operation (automatically move from activity to inactivity without having to clear interrupts)
// Enable activity and inactivity detection in reference mode (automatically accounts for gravity)
// uint8_t linkLoop, bool inactRef, bool inactEn, bool actRef, bool actEn
accel.writeActivityControl(accel.LINKLOOP_LOOP, true, true, true, true);
// Map the AWAKE bit to INT1 so activity can wake up the Photon
accel.writeIntmap1(accel.STATUS_AWAKE);
// Enable measuring mode with auto-sleep
// bool extClock, uint8_t lowNoise, bool wakeup, bool autosleep, uint8_t measureMode
accel.writePowerCtl(false, false, false, true, accel.MEASURE_MEASUREMENT);
state = BOOT_WAIT_STATE;
}
break;
case PUBLISH_STATE:
if (Particle.connected()) {
// The publish data contains 3 comma-separated values:
// whether movement was detected (1) or not (0) The not detected publish is used for battery status updates
// cell voltage (decimal)
// state of charge (decimal)
char data[32];
float cellVoltage = batteryMonitor.getVCell();
float stateOfCharge = batteryMonitor.getSoC();
snprintf(data, sizeof(data), "%d,%.02f,%.02f", awake, cellVoltage, stateOfCharge);
Particle.publish(eventName, data, 60, PRIVATE);
delay(2000); //2 Second Delay
Tempscanner1();
//Particle.publish("Function1 back at function");
delay(2000); // 2 second delay
// Wait for the publish to go out
stateTime = millis();
state = SLEEP_WAIT_STATE;
}
else {
// Haven't come online yet
if (millis() - stateTime >= MAX_TIME_TO_PUBLISH_MS) {
// Took too long to publish, just go to sleep
state = SLEEP_STATE;
}
}
break;
case SLEEP_WAIT_STATE:
if (millis() - stateTime >= TIME_AFTER_PUBLISH_MS) {
state = SLEEP_STATE;
}
break;
case BOOT_WAIT_STATE:
if (millis() - stateTime >= TIME_AFTER_BOOT_MS) {
// To publish the battery stats after boot, set state to PUBLISH_STATE
// To go to sleep immediately, set state to SLEEP_STATE
state = PUBLISH_STATE;
}
break;
case SLEEP_STATE:
// Sleep
System.sleep(ACCEL_INT_PIN, RISING, TIME_PUBLISH_BATTERY_SEC);
awake = ((accel.readStatus() & accel.STATUS_AWAKE) != 0);
state = PUBLISH_STATE;
stateTime = millis();
break;
}
}
void Tempscanner1(){
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;
if ( !ds.search(addr)) {
Serial.println("No more addresses.");
Serial.println();
ds.reset_search();
delay(250);
return;
}
// The order is changed a bit in this example
// first the returned address is printed
Serial.print("ROM =");
for( i = 0; i < 8; i++) {
Serial.write(' ');
Serial.print(addr[i], HEX);
}
// second the CRC is checked, on fail,
// print error and just return to try again
if (OneWire::crc8(addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return;
}
Serial.println();
// we have a good address at this point
// what kind of chip do we have?
// we will set a type_s value for known types or just return
// the first ROM byte indicates which chip
switch (addr[0]) {
case 0x10:
Serial.println(" Chip = DS1820/DS18S20");
type_s = 1;
break;
case 0x28:
Serial.println(" Chip = DS18B20");
type_s = 0;
break;
case 0x22:
Serial.println(" Chip = DS1822");
type_s = 0;
break;
case 0x26:
Serial.println(" Chip = DS2438");
type_s = 2;
break;
default:
Serial.println("Unknown device type.");
return;
}
// this device has temp so let's read it
ds.reset(); // first clear the 1-wire bus
ds.select(addr); // now select the device we just found
// ds.write(0x44, 1); // tell it to start a conversion, with parasite power on at the end
ds.write(0x44, 0); // or start conversion in powered mode (bus finishes low)
// just wait a second while the conversion takes place
// different chips have different conversion times, check the specs, 1 sec is worse case + 250ms
// you could also communicate with other devices if you like but you would need
// to already know their address to select them.
delay(1000); // maybe 750ms is enough, maybe not, wait 1 sec for conversion
// we might do a ds.depower() (parasite) here, but the reset will take care of it.
// first make sure current values are in the scratch pad
present = ds.reset();
ds.select(addr);
ds.write(0xB8,0); // Recall Memory 0
ds.write(0x00,0); // Recall Memory 0
// now read the scratch pad
present = ds.reset();
ds.select(addr);
ds.write(0xBE,0); // Read Scratchpad
if (type_s == 2) {
ds.write(0x00,0); // The DS2438 needs a page# to read
}
// transfer and print the values
Serial.print(" Data = ");
Serial.print(present, HEX);
Serial.print(" ");
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
Serial.print(data[i], HEX);
Serial.print(" ");
}
Serial.print(" CRC=");
Serial.print(OneWire::crc8(data, 8), HEX);
Serial.println();
// Convert the data to actual temperature
// because the result is a 16 bit signed integer, it should
// be stored to an "int16_t" type, which is always 16 bits
// even when compiled on a 32 bit processor.
int16_t raw = (data[1] << 8) | data[0];
if (type_s == 2) raw = (data[2] << 8) | data[1];
byte cfg = (data[4] & 0x60);
switch (type_s) {
case 1:
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
celsius = (float)raw * 0.0625;
break;
case 0:
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
// default is 12 bit resolution, 750 ms conversion time
celsius = (float)raw * 0.0625;
break;
case 2:
data[1] = (data[1] >> 3) & 0x1f;
if (data[2] > 127) {
celsius = (float)data[2] - ((float)data[1] * .03125);
}else{
celsius = (float)data[2] + ((float)data[1] * .03125);
}
}
// remove random errors
if((((celsius <= 0 && celsius > -1) && lastTemp > 5)) || celsius > 125) {
celsius = lastTemp;
}
fahrenheit = celsius * 1.8 + 32.0;
lastTemp = celsius;
Serial.print(" Temperature = ");
Serial.print(celsius);
Serial.print(" Celsius, ");
Serial.print(fahrenheit);
Serial.println(" Fahrenheit");
// now that we have the readings, we can publish them to the cloud
String temperature = String(fahrenheit); // store temp in "temperature" string
Particle.publish("Temperature1", temperature, PRIVATE); // publish to cloud
delay(2000); // 2 second delay
}