/* * brmhive -- low-power sensor data logger * * You can force wake and trigger resonr re-read using the Alert button. * * The info led will blink happily when doing all the work and stay dark * while asleep. Short blinks (up to a second) are o.k. Long blinks (more * than 1.5 seconds) indicate error. * * In case of trouble, try pressing Reset. */ /* PCF8583 uses pasky's fork at github that adds extra alarm capabilities. */ /* Required modification of cores/arduino/HardwareSerial.c: * Change RX_BUFFER_SIZE to 2, head and tail to uint8_t. */ /* TODO: Test w/o RX_BUFFER_SIZE hack. */ /* TODO: Move taddrs[] to PROGMEM. */ #include #include #include #include #include #include #include // #define DEBUG // Temperature bus scan. #define NUM_FSR 4 // number of weight sensors #define NUM_TEMP 55 // number of temperature sensors /* Pin definitions. */ #define auxPowerPin 6 /* Peripherial power transistor base. */ #define alertPin 2 /* Alert button. */ #define RTCPin 3 /* RTC alarm. */ #define infoPin 7 /* Info LED. */ #define oneWirePin 6 /* One-wire temperature sensors. */ /* SD Card is occupying fixed pins - SPI. */ /* RTC clock is occupying fixed pins - I2C. */ void powerdown_pins(void) { /* Before going to sleep, bring pins to the most low-power state. */ for (int i = 0; i <= 13; i++) { if (i == alertPin || i == RTCPin || i == infoPin || i == oneWirePin || i == auxPowerPin) continue; pinMode(i, OUTPUT); digitalWrite(i, HIGH); } /* TODO: Stop reading analog pins? */ } void blink(int count, int length) { for (int i = 0; i < count; i++) { digitalWrite(infoPin, LOW); delay(length); digitalWrite(infoPin, HIGH); delay(length); } digitalWrite(infoPin, LOW); } OneWire oneWire(oneWirePin); PCF8583 RTC(0xA0); Sd2Card card; SdVolume volume; SdFile root; SdFile file; void SD_init(void) { PRR &= ~(1<> 8; addr[2] = taddrs[i] & 0xff; addr[3] = 0x7d; addr[4] = 2; addr[5] = 0; addr[6] = 0; addr[7] = OneWire::crc8(addr, 7); digitalWrite(infoPin, HIGH); oneWire.reset(); oneWire.select(addr); oneWire.write(0x44); delay(800); int present = oneWire.reset(); if (present) { oneWire.select(addr); oneWire.write(0xbe); byte data[12]; for (int j = 0; j < 9; j++) data[j] = oneWire.read(); digitalWrite(infoPin, LOW); int16_t temp = (data[1] << 8) | data[0]; /* data is in 0.0625 increments, fixed-point *100. */ temp = temp * 6 + temp / 4; snprintf(scratch, sizeof(scratch), "%d=%d%c", i, temp, i == NUM_TEMP - 1 ? '\t' : ' '); append_scratch(); } else { blink(3, 1500); delay(1500); snprintf(scratch, sizeof(scratch), "%d=!%c", i, i == NUM_TEMP - 1 ? '\t' : ' '); append_scratch(); } delay(100); } } void collect_data(void) { digitalWrite(auxPowerPin, HIGH); SD_init(); get_timestamp(); collect_weights(); blink(2, 500); delay(500); collect_temps(); strcpy(scratch, "\r\n"); append_scratch(); SD_done(); digitalWrite(auxPowerPin, LOW); blink(3, 100); Serial.println("done"); } /* This is the one-time routine called when we are turned on. It should * set up the whole device and go through the drill. */ void setup(void) { init_device(); collect_data(); sleep(); } /* This is the repeat routine called all the time after setup(). * We sleep() between each two calls to it. */ void loop(void) { if (wake_cause == 1 || wake_cause == 2 || wake_cause == 3) { blink(2, 200); delay(1000); collect_data(); sleep(); } else { /* Something wrong happenned. Blink around a bit and try to go * to sleep. */ snprintf(scratch, sizeof(scratch), "unknown wake cause %d\r\n", wake_cause); append_scratch(); blink(3, 3000); sleep(); } }