-
Notifications
You must be signed in to change notification settings - Fork 25
/
attiny_photoresistor_i2c.ino
150 lines (122 loc) · 2.77 KB
/
attiny_photoresistor_i2c.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
* Set I2C Slave address. You can have multiple sensors with different addresses
*/
#define I2C_SLAVE_ADDRESS 0x13
/*
* How often measurement should be executed
* One tick is more less 0.5s, so 1 minute is 120 ticks
* This executes measurements every 2 minutes, so 120s, 120000 ms
*/
#define MAX_TICK 120000
#define STATUS_PIN_1 4
#define ADC_PIN A3
#define LPF_FACTOR 0.5
#include <TinyWireS.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#ifndef TWI_RX_BUFFER_SIZE
#define TWI_RX_BUFFER_SIZE ( 16 )
#endif
volatile uint8_t i2c_regs[] =
{
0, //older 8
0 //younger 8
};
volatile byte reg_position = 0;
const byte reg_size = sizeof(i2c_regs);
/*
* 0=16ms
* 1=32ms
* 2=64ms
* 3=128ms
* 4=250ms
* 5=500ms
* 6=1 sec,
* 7=2 sec,
* 8=4 sec,
* 9= 8sec
*/
void setup_watchdog(int ii) {
byte bb;
int ww;
if (ii > 9 ) ii=9;
bb=ii & 7;
if (ii > 7) bb|= (1<<5);
bb|= (1<<WDCE);
ww=bb;
MCUSR &= ~(1<<WDRF);
// start timed sequence
WDTCR |= (1<<WDCE) | (1<<WDE);
// set new watchdog timeout value
WDTCR = bb;
WDTCR |= _BV(WDIE);
}
/*
* Watchdog Interrupt Service is executed when watchdog timed out
*/
ISR(WDT_vect) {
digitalWrite(STATUS_PIN_1, LOW);
}
volatile unsigned int lightMeter;
/**
* This function is executed when there is a request to read sensor
* To get data, 2 reads of 8 bits are required
* First requests send 8 older bits of 16bit unsigned int
* Second request send 8 lower bytes
* Measurement is executed when request for first batch of data is requested
*/
void requestEvent()
{
TinyWireS.send(i2c_regs[reg_position]);
reg_position++;
if (reg_position >= reg_size)
{
reg_position = 0;
}
}
void setup() {
/*
* Setup I2C
*/
TinyWireS.begin(I2C_SLAVE_ADDRESS);
TinyWireS.onRequest(requestEvent);
/*
* Set pins
*/
pinMode(STATUS_PIN_1, OUTPUT);
pinMode(ADC_PIN, INPUT);
/*
* Start watchdog timer
*/
setup_watchdog(6);
}
unsigned int tick = 0;
unsigned long lastReadout = 0;
int smooth(int data, float filterVal, float smoothedVal){
if (filterVal > 1){ // check to make sure params are within range
filterVal = .99;
}
else if (filterVal <= 0){
filterVal = 0;
}
smoothedVal = (data * (1 - filterVal)) + (smoothedVal * filterVal);
return (int)smoothedVal;
}
void loop() {
set_sleep_mode(SLEEP_MODE_PWR_SAVE);
sleep_enable();
sleep_mode();
sleep_disable();
unsigned long currentMillis = millis();
/*
* On tick value 0, do measurements
*/
if (abs(currentMillis - lastReadout) > MAX_TICK) {
int raw_value = analogRead(ADC_PIN);
lightMeter = smooth(raw_value, LPF_FACTOR, lightMeter);
i2c_regs[0] = lightMeter >> 8;
i2c_regs[1] = lightMeter & 0xFF;
digitalWrite(STATUS_PIN_1, HIGH);
lastReadout = currentMillis;
}
}