Hello to all,
I'm currently building a wifi weather station. For monitoring wind speed, wind direction and rain, I use ATTINYs.
One ATTINY85 is used for wind speed and later on for rain gauge. Currently I use a reed switch for wind detection, maybe other sensors like hall will be better but it works as starting point.
However, after digging into I2C with Attiny, I got some working code using TinyWireS Library. Main Time, ATTINY is in sleep mode, at pin change interrupt, I count wind variables and go back to sleep. If I2C request occurs, it sends data to master.
All this works great for a couple of minutes but it then stops responding to I2C calls. It is build up on a breadboard, I added external Pullups at ATTINY for SCL and SDA (4k7 Ohm)
I also tried it without sleep and without pin change interrupts, but it still crashes after a while. Master (Wemos D1 mini) is reading every 2 seconds for debugging purposes.
Does anyone has some hints to me what's going wrong? This is my slave code, ATTINY85 is running at 8MHz internal
// Code for the ATtiny85
#include <TinyWireS.h>
#define I2C_SLAVE_ADDRESS 0x4 // Address of the slave
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
// pins of wind vane positions
const int pinWindCount = 3;
const byte chksum1 = 200; // begin of transfer
const byte chksum2 = 251; // end of transfer
volatile int response = 0;
volatile int senddata = 1;
uint8_t windcount1 = 0;
uint8_t windcount2 = 0; // Overflow variable 1
uint8_t windcount3 = 0; // Overflow variable 2
volatile bool thiswind;
volatile bool lastwind = HIGH;
void reboot() {
cli();
WDTCR = 0xD8 | WDTO_1S;
sei();
wdt_reset();
while (true) {}
} //reboot
void setup()
{
MCUSR &= ~(1 << WDRF); // reset status flag
wdt_disable();
tws_delay(100);
TinyWireS.begin(I2C_SLAVE_ADDRESS); // join i2c network
USICR |= 1 << USIWM0; // Clock stretching?
TinyWireS.onRequest(requestEvent);
pinMode(pinWindCount, INPUT_PULLUP);
digitalWrite(pinWindCount, HIGH);
} // setup
void sleep() {
GIMSK |= _BV(PCIE); // Enable Pin Change Interrupts
PCMSK |= _BV(PCINT3); // Use PB3 as interrupt pin
// PCMSK |= _BV(PCINT4); // Use PB4 as interrupt pin
ADCSRA &= ~_BV(ADEN); // ADC off
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above statement
sleep_enable(); // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
sei(); // Enable interrupts
sleep_cpu(); // sleep
cli(); // Disable interrupts
PCMSK &= ~_BV(PCINT3); // Turn off PB3 as interrupt pin
// PCMSK &= ~_BV(PCINT4); // Turn off PB4 as interrupt pin
sleep_disable(); // Clear SE bit
ADCSRA |= _BV(ADEN); // ADC on
//WDTCR |= _BV(WDIE); // Watchdog on
sei(); // Enable interrupts
} // sleep
ISR(PCINT0_vect) {
// DO NOTHING HERE, CATCH EVERYTHING IN LOOP
}
void loop()
{
// This needs to be here
TinyWireS_stop_check();
// Check wind count
thiswind = digitalRead(pinWindCount);
if (thiswind != lastwind) { //check if value has changed since last time
if (thiswind == HIGH) { //value has changed - was it rising edge?
// do we get an overflow at windcount 1?
if (windcount1 == 255 )
{
// do we get an overflow on windcount 2?
if (windcount2 == 255)
{
windcount3++;
}
windcount2++;
}
windcount1++;
}
lastwind = thiswind; //switch state ready for next time
}
// Go back to sleep
tws_delay(2); // wait 2ms for software debouncing
sleep();
}
// Gets called when the ATtiny receives an i2c request
void requestEvent()
{
// cli();
switch (senddata) {
case 1: // first byte requested send start checksum
TinyWireS.send(chksum1);
senddata = 2;
break;
case 2: // 2nd byte requested, send first counter
TinyWireS.send(windcount1);
senddata = 3;
break;
case 3: // 3rd byte requested, send first overflow counter
TinyWireS.send(windcount2);
senddata = 4;
break;
case 4: // 4th byte requested, send 2nd overflow counter
TinyWireS.send(windcount3);
senddata = 5;
break;
case 5: // 5th byte requested, send end checksum
TinyWireS.send(chksum2);
senddata = 1;
break;
default:
TinyWireS.send(111);
senddata = 1;
}
// sei();
}