// // main.c : AVR uC code for flukso sensor board // // Copyright (c) 2008-2009 jokamajo.org // 2010 flukso.net // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ #include #include #include "wiring/wiring_private.h" #include "main.h" #include // pin/register/ISR definitions #include // eeprom library #include // watchdog timer library #include // variable declarations volatile struct state aux[4] = {{false, false, START, 0, 0}, {false, false, START, 0, 244}, {false, false, START, 0, 0}, {false, false, START, 0, 0}}; volatile struct sensor EEMEM EEPROM_measurements[4] = {{SENSOR0, START}, {SENSOR1, START}, {SENSOR2, START}, {SENSOR3, START}}; volatile struct sensor measurements[4]; volatile uint8_t muxn = 0; // interrupt service routine for INT0 ISR(INT0_vect) { measurements[2].value++; aux[2].pulse = true; } // interrupt service routine for INT1 ISR(INT1_vect) { measurements[3].value++; aux[3].pulse = true; } // interrupt service routine for PCI2 (PCINT20) /** ISR(PCINT2_vect) { if (aux[4].toggle == false) { aux[4].toggle = true; } else { measurements[4].value++; aux[4].pulse = true; aux[4].toggle = false; } } **/ // interrupt service routine for ADC ISR(TIMER2_OVF_vect) { // read ADC result // add to nano(Wh) counter if (muxn < 2) { MacU16X16to32(aux[muxn].nano, METERCONST, ADC); if (++aux[muxn].count > 487) { aux[muxn].adc = ADC; aux[muxn].toggle = true; aux[muxn].count = 0; } if (aux[muxn].nano > 1000000000) { measurements[muxn].value++; aux[muxn].pulse = true; aux[muxn].nano -= 1000000000; } } // rotate amongst the available ADC input channels (0 to 7) muxn++; muxn &= 0x7; // but only use ADC0 and 1 if (muxn < 2) { ADMUX &= 0xF8; ADMUX |= muxn; // start a new ADC conversion ADCSRA |= (1< moved the call to this function to start of the main loop, before init // clock settings: divide by 8 to get a 1Mhz clock, allows us to set the BOD level to 1.8V (DS p.37) CLKPR = (1< fTOV2 = 1000kHz / 256 / 1 = 3906.24Hz (DS p.158) TCCR2B |= (1< 1000kHz / 8 = 125kHz (DS p.258) ADCSRA |= (1<value; sei(); strcpy(message, "pls "); break; case POWER: cli(); uint16_t adc = aux->adc; sei(); MacU16X16to32(value, adc, POWERCONST); value /= 1000; strcpy(message, "pwr "); break; } strcpy(&message[4], measurement->id); strcpy(&message[36], ":0000000000\n"); do { // generate digits in reverse order message[i--] = '0' + value % 10; // get next digit } while ((value /= 10) > 0); // delete it printString(message); } void loop() { uint8_t i; // check whether we have to send out a pls or pwr to the deamon for (i=0; i<4; i++) { if (aux[i].pulse == true) { send(PULSE, (const struct sensor *)&measurements[i], (const struct state *)&aux[i]); aux[i].pulse = false; } if (aux[i].toggle == true && i < 2) { send(POWER, (const struct sensor *)&measurements[i], (const struct state *)&aux[i]); aux[i].toggle = false; } } wdt_reset(); } int main(void) { uint8_t i; WDT_off(); setup(); // insert a startup delay of 20s to prevent interference with redboot // interrupts are already enabled at this stage // so the pulses are counted but not sent to the deamon for (i=0; i<4; i++) _delay_ms(5000); serialFlush(); printString("\n"); WDT_on(); for (;;) loop(); return 0; }