/* * Tiny 10 Moisture sensore and indicator v2.2 * with voltage detection works 2.4v is trigger * * Sherman Stebbins * 2022-02-17 * * Firmware v2.2 * * * Attiny10; +====+; SCK -> PB0 |* | PB3 (RESET); GND | | Vcc; MOSI -> PB1 | | PB2 ; +====+
Updated 2.1 on 3-19-22changed light alerts and added moreset at 8mhz in arduino ide to get correct timing2** Updated 3-19/22* changed when lit and more green and red light alert.* Faster is less good. ** Updated 5/6/23* Changed battery low code to include ISR.. * and fixed low voltage, on test chip, * triggered at 2.35v, But changed current from 4uA to 46uA !!* So Put crap back, now low voltage does not work. * VLMCSR = 0; //shutdown VLM* was added back in.** Updated 5/8/23* FIXED low voltage detection and works and now sleeps at about 5ua!!* also dropped clock back to 1mhz, 8mhz was over kill.* * Green slow - full of water* Green fast - good on water* Green and red - medium on water* Red slow - low water* Red Fast - dry on water** Alternating Red and Green - Battery low** */#define F_CPU 1000000UL#include <util/delay.h>#include <avr/interrupt.h>
#define Moisture PB0#define RedLed PB1#define GreenLed PB2//#define SleepTimes 4 //8=58 sec //4=29 secvolatile uint8_t SleepTimes=4; //8=58 sec //4=29 sec //2=15sec //1=8sec//volatile static uint8_t LowVoltage =0;
volatile unsigned char count __attribute__((section(".noinit"))); // Not cleared on RESETvolatile unsigned char LowVoltage __attribute__((section(".noinit"))); // Not cleared on RESETvoid goToSleep(void);uint8_t analog_read(uint8_t pin);void LightLed(uint8_t Led);void LedOff(void);
int main(void){ CCP = 0xD8; // unlock protected register //CLKPSR = 0; // No divider full 8mhz CLKPSR = 0b00000011; //just set to default to test VLMCSR |= (1<<VLM0)|(1<<VLM1)|(1<<VLMIE); _delay_us(30);// VLMCSR = 0b01000011; WDTCSR &= ~(1<<WDE); //must have or won't sleep WDTCSR &= ~(1<<WDIE); DDRB = 0b00000110; sei(); while(1){
//xc mm cc if(count==0){ //if Battery below 2.4v gives warning light flash if(VLMCSR & (1<<VLMF)){ //VLMCSR & 0b10000000 either one reads VLMF flag for(int i=0;i<3;i++){ LightLed(GreenLed); _delay_ms(10); LedOff(); LightLed(RedLed); _delay_ms(10); LedOff(); LowVoltage=1; } } uint8_t Wetness=0; Wetness = analog_read(Moisture); //get moisture reading for(int i=0;i<12;i++){ //8 //display moisture level: if(Wetness >= 242){ if(LowVoltage){ LightLed(GreenLed); _delay_ms(15); LedOff(); _delay_ms(15); }else{ LightLed(GreenLed); _delay_ms(150); LedOff(); _delay_ms(150); } SleepTimes=4; //4 //8=58 sec //4=29 sec //2=15sec //1=8sec }else if(Wetness <=242 && Wetness >= 230){ if(LowVoltage){ LightLed(GreenLed); _delay_ms(15); LedOff(); _delay_ms(15); }else{ LightLed(GreenLed); _delay_ms(50); LedOff(); _delay_ms(50); } SleepTimes=4; //4 //8=58 sec //4=29 sec //2=15sec //1=8sec }else if(Wetness <=229 && Wetness >= 218){ if(LowVoltage){ LightLed(RedLed); LightLed(GreenLed); _delay_ms(15); LedOff(); _delay_ms(15); }else{ LightLed(RedLed); LightLed(GreenLed); _delay_ms(100); LedOff(); _delay_ms(100); } SleepTimes=2; //2 //8=58 sec //4=29 sec //2=15sec //1=8sec }else if(Wetness <=217 && Wetness >= 200){ if(LowVoltage){ LightLed(RedLed); _delay_ms(15); LedOff(); _delay_ms(15); }else{ LightLed(RedLed); _delay_ms(150); LedOff(); _delay_ms(150); } SleepTimes=1; //8=58 sec //4=29 sec //2=15sec //1=8sec }else if( Wetness < 200){ if(LowVoltage==1){ LightLed(RedLed); _delay_ms(5); LedOff(); _delay_ms(5); }else{ LightLed(RedLed); _delay_ms(50); LedOff(); _delay_ms(50); } SleepTimes=1; //8=58 sec //4=29 sec //2=15sec //1=8sec // } } LowVoltage=0; } } count++; if(count>=SleepTimes){ count=0; } goToSleep(); }}//low voltage interuptISR(VLM_vect){ /* LowVoltage=1; //didn't carry over due to sleep DUHHHH use volitile.. like: volatile unsigned char count __attribute__((section(".noinit"))); // Not cleared on RESET */ LowVoltage=1; }
void goToSleep(void){ VLMCSR = 0; //shutdown VLM ADCSRA &= ~(1<<ADEN); //shut off ADC
SMCR |= (1<<2); //SMCR.SM bit 2 (010) Power-down SMCR |= (1<<0); //SMCR.SE =1; SET JUST before Sleep starts sei() ; //set Global Interrupt Enable //__asm__ __volatile__("sleep") ; //enter sleep, waiting for interrupt -- This worked great!!! WDTCSR = 0b01100001; //1000 4 sec 0111 2 sec watchdog timer 1001 8 sec.// WDTCSR |= (1<<WDIE)|(1<<WDP3)|(1<<WDP0)|(1<<WDE); //1000 4 sec 0111 2 sec watchdog timer 1001 8 sec. __asm__ __volatile__ ( "sleep" "\n\t" :: ); //Sleep instruction to put controller to sleep (found this syntax later, probably more proper)// cli(); //wake: // VLMCSR |= (1<<VLM0)|(1<<VLM1)|(1<<VLMIE);}
void LedOff(void){ PORTB &= ~(1<<PB1); PORTB &= ~(1<<PB2);}
void LightLed(uint8_t Led){ PORTB |= (1<<Led);}
uint8_t analog_read(uint8_t pin){ switch(pin) { case PB0: ADMUX = 0; DIDR0 = _BV(ADC0D); break; // ADC0 case PB1: ADMUX = _BV(MUX0); DIDR0 = _BV(ADC1D); break; // ADC1 case PB2: ADMUX = _BV(MUX1); DIDR0 = _BV(ADC2D); break; // ADC2 //default: ADMUX = 0; break; }
ADCSRA |= _BV(ADEN); // Enable ADC ADCSRA |= _BV(ADSC); // Run single conversion while(bit_is_set(ADCSRA, ADSC)); // Wait conversion is done
// Read values return ADCL;}