/*
Air Purifier
with a fan, a LED and a battery.
BOARD: ATtiny412/402/212/202/
Chip: ATtiny402
Clock Speed: 20MHz
Programmer: jtag2updi (megaTinyCore)
*/
#include <avr/sleep.h> //Power Management and Sleep Modes
#include <avr/interrupt.h>
//pins definitions
//ATTINY85 //ATTINY402
#define STAT_PIN PINB5 //PA6 2
#define VBAT_PIN PINB3 //PA7 3
#define SPEED_CTR_PIN PINB1 //PA1 4
#define PBIN_PIN PINB0 //PA2 5
#define PWRON_OFF_PIN PINB4 //PA0 6
#define LED_CTR_PIN PINB2 //PA3 7
//PWM
#define SPEED_LOW 153 //PWM 60%
#define SPEED_MIDDLE 204 //PWM 80%
#define SPEED_HIGH 254 //PWM 100%
//delays
#define B_DIFF 200 //100 millisecond for button deboounce
#define B_DIFF2 2000 //2000 millisecond for state change when the button is pressed
#define DISP_PBIN 2000 //2000 millisecond for display when the button is pressed
#define blnk100ms 100 //blink 100ms
#define blnk200ms 200 //blink 200ms
#define blnk500ms 500 //blink 500ms
#define blnk1s 1000 //blink 1s
#define blnk2s 2000 //blink 2s
//flags
bool blnkOn = false;
bool saveStatePBIN = false;
bool statePBIN = false;
bool dispPBIN = false;
bool speedLow = false;
bool speedMid = false;
bool speedHigh = false;
bool stateChanged = false;
//battery
const float BAT_FULL = 4.2; //736 //4.2v
const float BAT_EMPTY = 3.2; //540 //3.2v
bool batteryLow = false;
bool batteryCharge = false;
bool batteryFull = false;
uint16_t blnkTimeOn = 0;
uint16_t blnkTimeOff = 0;
int SPEED_PWM = 0; //PWM value for fan
//times variable
unsigned long saveTime = 0;
unsigned long blnkTime = 0;
unsigned long dispPbInTime = 0;
ISR(PCINT0_vect) {
GIMSK &= ~0b00100000; // Turn off pin change interrupts
sleep_disable();
}
void sleep() {
sleep_enable();
noInterrupts();
GIMSK |= 0b00100000; // Turn on pin change interrupts
PCMSK = 0b00000001; // turn on interrupts on pins PB0
interrupts();
sleep_cpu();
}
void setup() {
//pins set up
pinMode(STAT_PIN, INPUT_PULLUP);
pinMode(VBAT_PIN, INPUT);
pinMode(SPEED_CTR_PIN, OUTPUT);
pinMode(PBIN_PIN, INPUT);
pinMode(LED_CTR_PIN, OUTPUT);
pinMode(PWRON_OFF_PIN, OUTPUT);
//PORTA.PIN3CTRL = 0b0000100; //PA3 digital input buffer and pull-up is disabled
//reference 1,1V
analogReference(INTERNAL1V1);
//set sleep mode and put into sleep
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep();
}
void loop() {
if (!speedLow && !speedMid && !speedHigh)
{
digitalWrite(PWRON_OFF_PIN, LOW);
sleep(); //put into sleep
}
else
{
digitalWrite(PWRON_OFF_PIN, HIGH);
}
//pushbutton state read
statePBIN = digitalRead(PBIN_PIN);
//change state when button is pressed
if (statePBIN && !saveStatePBIN && millis() - saveTime > B_DIFF)
{
saveTime = dispPbInTime = millis();
if (!speedLow && !speedMid && !speedHigh)
{
speedLow = true;
SPEED_PWM = SPEED_LOW; //analogWrite(SPEED_CTR_PIN, SPEED_LOW);
}
else if (speedLow)
{
speedLow = false;
speedMid = true;
SPEED_PWM = SPEED_MIDDLE; //anlogWrite(SPEED_CTR_PIN, SPEED_MIDDLE);
}
else if (speedMid)
{
speedMid = false;
speedHigh = true;
SPEED_PWM = SPEED_HIGH; //analogWrite(SPEED_CTR_PIN, SPEED_HIGH);
}
else if (speedHigh)
{
speedHigh = false;
SPEED_PWM = 0; //analogWrite(SPEED_CTR_PIN, 0);
}
dispPBIN = true;
saveStatePBIN = true;
}
if (!statePBIN && saveStatePBIN && millis() - saveTime > B_DIFF)
{
saveTime = millis();
saveStatePBIN = false;
}
if (dispPBIN && millis() - dispPbInTime > DISP_PBIN)
{
dispPBIN = false;
}
//read battery charge
//5v = 1023
uint16_t readingVoltage = analogRead(VBAT_PIN);
float vBat = (float)readingVoltage * 5 / 1023;
//discharging
if (digitalRead(STAT_PIN))
{
//full battery
if (vBat > BAT_FULL)
{
batteryLow = false;
batteryCharge = false;
batteryFull = true;
}
//low battery
else if (vBat < BAT_EMPTY)
{
batteryLow = true;
batteryCharge = false;
batteryFull = false;
speedLow = false;
speedMid = false;
speedHigh = false;
SPEED_PWM = 0;
}
else
{
batteryLow = false;
batteryCharge = false;
batteryFull = false;
}
}
//charging
else
{
batteryLow = false;
batteryCharge = true;
batteryFull = false;
}
//set blink delay depends on state
if (dispPBIN)
{
blnkTimeOn = blnk200ms;
blnkTimeOff = blnk200ms;
}
else if (batteryCharge)
{
blnkTimeOn = blnk500ms;
blnkTimeOff = blnk500ms;
}
else if (batteryLow)
{
blnkTimeOn = blnk200ms;
blnkTimeOff = blnk2s;
}
//blink
if (blnkOn && millis() - blnkTime > blnkTimeOn)
{
blnkOn = false;
blnkTime = millis();
}
if (!blnkOn && millis() - blnkTime > blnkTimeOff)
{
blnkOn = true;
blnkTime = millis();
}
if (batteryFull && !dispPBIN)
{
blnkOn = true;
}
if (!batteryFull && !batteryLow && !batteryCharge && !dispPBIN)
{
blnkOn = false;
}
//write blink output
digitalWrite(LED_CTR_PIN, blnkOn);
//write pwm value
analogWrite(SPEED_CTR_PIN, SPEED_PWM);
}