Last active
February 11, 2019 18:36
-
-
Save CharlieASVZ/729b30dbed9a3e37372475c86961c948 to your computer and use it in GitHub Desktop.
EFCS_Arduin_DigiSpark_for_Airsoft
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is free software released under: GNU General Public License (GPL), Version 3 | |
// for more information about GNU GPLv3 look here: https://www.gnu.org/licenses/gpl.html | |
// so in principle you can use and modify it for anything you want, as long as it remains free software. | |
//* helpful links: | |
//* http://digistump.com/products/1 // Board | |
//* https://digistump.com/wiki/digispark/tutorials/connecting // Start programming | |
//* https://digistump.com/wiki/digispark/quickref // which PIN to use | |
//* https://www.arduino.cc/reference/en/#page-title // help for programming | |
//* originally build for DigiSpark ATTiny85 and Cyma CM0.30 AEP on 2s Lipo, for ohter setups you may have to adjust the settings. | |
//* WARNING: Will only work with a lot of mechanical manipulations for installing the microswitches and Mosfets in your AEP, or other gearboxes. | |
//* external safety switch recommend. if you want to disconnecting from battery for safety, you have to deal with 5s delay or modify the bootloader | |
//* Be aware that _PIN 3 and _PIN 4 are used for USB connection(only on Digispark Bord), can be buggy. and not optimal for a I/O switch. | |
//* _PIN 3 only have ca. +3.1V(working surprisingly well on my Board) to GND, _PIN 4 ca. 2V -so dont use for MosfetOutput - maybee with external Pullup resistor. | |
//* _PIN 4 here is used with 2.2KOhm to _PIN1 for using both I/O switch and USB programming capability - this is maybee not a recommend solution(it just works by chance) | |
//* if you don't need active breaking change the BREAKFET_PIN number witch CUTOFF_PIN number to avaoid extra resistor(only for Digispark because specific Pin restrictions) | |
//* _PIN 5 on some Digispark boards is used as reset- don`t use forI/O switch via GND... *using for voltagereading with highOhm resistors works fine | |
//* !!!!!!!!!!DISCONNECT _PIN 3 and _PIN 4 from GND for Programming via USB *simply use normal microswitch, which is open on default (only necessary for DigiSpark) | |
//* for battery voltage check you need to build a voltage divider, so PIN_5 never see more than 5v. PS: you need different values for R1/R2 for using 3s 11.1v Lipo. | |
//* WARNING: be careful with precocking and use it only at YOUR OWN RISK, because more stress on Gearbox and parts. (in the course of this i broke one AEP shell by the ARL mounting) | |
//* step by step instruction for installation: | |
//* - you need Arduino IDE with downloaded Bounce2.h and EEPROM.h files added to your libraries folder | |
//* - choose Your Arduino board (and check the Pinouts, if your board is different) this variation only fits DigiSpark | |
//* - DigiSpark Board with 2added resistors for voltageDivider in this case for 2s Lipo: GND--2.2MOhm--P5--1.5MOhm--VIN | |
//* - Connect Lipo via GND to+ VIN_PIN and switches from GND to _PIN XYZ. // VIN pin takes 7-12v,without extra heatsink. I used 2extra wires from battery+/- to Digispark GND/VIN | |
//* - Multimeter for general checking and improving Measured5vReference (recommend, if you want any precise voltage) | |
//* - Use IRLB-3034PBF MOSFET with 2.2 KOhm between Gain and Source, suppressor Diode, and 100 Ohm resistor to _PIN 1 recommend. | |
//* - if you don't use activebreaking be sure to change CUTOFF switch to _PIN 0, else (look above why) and connect_PIN 4 with 2.2KOhm to _PIN1 | |
//* - Use with Microswitches on Trigger and Cutofflever, for Fireselector use normal switches, for AEP there are a few little difficult modifications: | |
//* for CutOff on AEP something like DF-P1L-0P-Z(Conrad)(tested) or maby something like ESE11(DigiKey),ESE-31(DigiKey) for AEGs you can also look what BTC and ASCU are using | |
//* - check and adapt the following values in the Code, recommend in(): R1, R2, Measured5vReference(5.0), CellCount(2.0 or 3.0), LOW_VOLTAGE(3.4), preCockingTime(0), aktiveBreakingTime(0), | |
//* modeVoltageProtectionEnabled (true), modePreCockingEnabled (false), modeAktiveBreakingEnabled (false). | |
//* - throw everything together and hope it works | |
//* | |
//* these steps are without installing P-channel Fet for activebreaking: IRF4905PBF MOSFET | |
//* - for 7.4Lipo you can connect the P-Channel Fet the following: Source==Motor(+)==Vcc+(7,4v), Drain==Motor(-) , Gate==OutputPin. (+resistors same as N-ChannelFet+ TVS diode) | |
//* - If set OutputPin:LOW (to GND), P-Fet see -7,4v and opens, if set to HIGH P-Fet see -7,4v+5v == -2,4v and hopefully does not yet opens(look datasheet) | |
//* - maybe there is a better way around and i don't think this works fine for 11.1vLipo (you should look on datasheet and modify the right voltages to switch the fet via the Gate) | |
//* for trigger programming options please look direct into the Code behind Setup | |
//* you have to hold trigger down while connecting battery and choose option by fireselector and still holding or resetting trigger while first ten beeps(look in code down there) | |
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
#include <avr/power.h> | |
#include <avr/sleep.h> | |
#include <Bounce2.h> // no standard library - eliminates oscillation while switch contacts are at closing procedure | |
#include <EEPROM.h> // https://github.com/thomasfredericks/Bounce2 - Download - adding to Arduino libraries folder | |
// these Pin numbers refer to DigiSpark P0 - P5 , for other Boards this changes of course | |
#define BREAKFET_PIN 0 // active breaking, need extra P-Channel-FET *if not used, it is easier to change pin numbers with CUTOFF_PIN so you finally get "#define CUTOFF_PIN 0" ,alternative look below and solder extra resistor | |
#define MOSFET_PIN 1 // Mosfet Gate * LED is coupled to _PIN 1 | |
#define TRIGGER_PIN 2 // Switch Unit | |
#define FIRESELECTOR_PIN 3 // Fire Selector * if switch open == SEMI | |
#define CUTOFF_PIN 4 // CutOff Switch * if using DigiSpark and don't have another free Pin to use: 22kOhm between _PIN4 and _PIN1 for external pullup(because _PIN4 used for USB causes low HIGH level), | |
// or use pullup resistor via Vcc... but then you have to remove it for every programming | |
//Voltage input on _PIN 5 // Vin from voltage divider * please note, for DigiSpark the analogue read is different named -(command:"analogRead(0)" will read this _PIN 5 /P5), | |
#define R1 2.10 // R1 in Mohm * necessary for voltage divider | |
#define R2 1.48 // R2 in Mohm * for 7.4Lipo, for 11.1 please calculate new | |
#define Measured5vReference 4.70 // measure your exact internal 5v voltage supply with multimeter for more accuracy, or try numbers until it works accurate | |
#define LOW_VOLTAGE 3.7 // Shutdown Voltage for one cell * please use floating numbers, like 3.3 , 3.4 , 3.5 .... 3.6 | |
#define preCockingTime 30 // time in ms * for testing use fully charged battery | |
#define activeBreakingTime 0 // time in ms * if wanted, you can decrease intensity by setting delay time before breaking. | |
// 0ms(recommend) means instant, most intense breaking. please don`t use to high numbers, because this delay isn`t interrupted by next trigger input and can slow down complete cycle | |
boolean firstSwitchOn =true; // for voltage measuring direct after battery connection * maybee turn off for less initial delay | |
boolean modeVoltageProtectionEnabled =true; // true = activated; false = deactivated //dont sure if works reliable! | |
float CellCount = 2.0; // you can choose later via trigger programming between 2.0 and 3.0 | |
boolean modePreCockingEnabled =false; // true == enabled - not recommend for AEPs | |
boolean modeActiveBreakingEnabled =false; // short circuit on Motor via BreakingFet directly on Motor - this will cause more stress on your Gearbox and motorbrushes, but helps against burst and doubles in SEMI | |
int eeAddressVoltageProtection = 0; // adress for EEPROM(permanent onboard memory) to safe the trigger programmed settings | |
int eeAddressCellCount = 1; | |
int eeAddressActiveBreaking = 2; | |
int eeAddressPreCock = 3; | |
/*struct ConfigurationSettings { // not implemented stuff for more complex trigger programming in future... | |
float CellCount | |
float LOW_VOLTAGE | |
int preCockingTime | |
activeBreakingTime | |
boolean modePreCockingEnabled | |
boolean modeVoltageProtectionEnabled | |
boolean modeAktiveBreakingEnabled | |
}; | |
ConfigurationSettings settings = { | |
2.0, | |
3.4, | |
30, | |
0, | |
false, | |
true, | |
true | |
}; | |
EEPROM.put(0,settings); uncomment this the first time to initialize the EEPROM to "settings", then comment it out | |
EEPROM.get(0, settings); | |
// void loop(void) | |
//{ | |
// if(somethingInEprommChanged) | |
// { | |
// EEPROM.put(0, settings); | |
// } | |
//} */ | |
int cutOff = 0; | |
int trigger = 0; | |
int fireselector = 0; | |
float digitalVoltageread = 0; // measured voltage at PIN_5 to digital 0-1023 | |
float voltageDivider = 0; | |
float realVoltage = 0; | |
float voltagePerCell = 4.2; // only estimated, inreality one cell can be bad and below the ohters | |
unsigned long lastVoltageCheck = 0; // timestamp when voltage was read last | |
unsigned long lastshot = 0; // timestamp when last time fireing | |
unsigned long timeAfterTriggerInput = 0; // time mark for Cutofftimer if defect CUTOFF_PIN | |
Bounce debouncer0 = Bounce(); // Debouncer3 for the CUTOFF_PIN 0 | |
Bounce debouncer2 = Bounce(); // Debouncer2 for the TRIGGER_PIN 2 | |
Bounce debouncer3 = Bounce(); // Debouncer3 for the FIRESELECTOR_PIN 3 | |
void setup() //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
{ | |
pinMode(CUTOFF_PIN, INPUT_PULLUP); // Pin setup with internal Pullup resistor // evtl. zusammenfassen debouncer0.attach(CUTOFF_PIN,INPUT_PULLUP); | |
debouncer0.attach(CUTOFF_PIN); // Attach the debouncer0 | |
debouncer0.interval(3); // Debounce interval in ms // maybe can try the recommend 5ms | |
pinMode(MOSFET_PIN, OUTPUT); // Mosfet gate pin set to output | |
pinMode(TRIGGER_PIN, INPUT_PULLUP); // Pin setup with internal Pullup resistor // Without resistor in case of an open switch the digital pin is "free" and can be randomly true or false | |
debouncer2.attach(TRIGGER_PIN); // Attach the debouncer2 // Pullup resistor connects to +5V, so the _PIN is HIGH open and closed LOW, becaue schort-circuit do GND | |
debouncer2.interval(3); // Debounce interval in ms - time for oscillations to swing out | |
pinMode(FIRESELECTOR_PIN, INPUT_PULLUP); // Pin setup with internal Pullup resistor // _PIN 3 connects also to USB+ and caus problems with lower voltage | |
debouncer3.attach(FIRESELECTOR_PIN); // Attach the debouncer3 | |
debouncer3.interval(3); // Debounce interval in ms | |
pinMode(BREAKFET_PIN, OUTPUT); // Pin for Motorbreaking | |
voltageDivider = R1 / (R1 + R2); | |
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode for low voltage cutoff | |
EEPROM.get(eeAddressPreCock, modePreCockingEnabled); // get modePreCockingEnabled from EEPROM | |
EEPROM.get(eeAddressCellCount, CellCount); | |
EEPROM.get(eeAddressVoltageProtection, modeVoltageProtectionEnabled); // get modeVoltageProtection from EEPROM | |
EEPROM.get(eeAddressActiveBreaking, modeActiveBreakingEnabled); | |
digitalWrite(BREAKFET_PIN, HIGH); //remember:P-Channel Fet, HIGH means deactivate Fet * here only necessary to be sure breakfet don't do anything stupid without declaration | |
debouncer2.update(); // first normal trigger update | |
trigger = debouncer2.read(); // write status | |
if (trigger == LOW) // pull trigger, while connecting battery for START trigger programming......................................................................... | |
{ | |
for (int i=0; i <= 20; i++) | |
{ | |
for (int u=0; u <= 30; u++) | |
{ | |
digitalWrite(MOSFET_PIN, HIGH); // 20 fast, high noise motor vibration | |
delayMicroseconds(100); | |
digitalWrite(MOSFET_PIN, LOW); | |
delayMicroseconds(500); | |
debouncer2.update(); // second trigger update, need updated while beeping important to detect if trigger was released in this (beeping) time period | |
trigger = debouncer2.read(); // write status | |
} | |
delay(100); | |
} | |
debouncer3.update(); // first normal fireselector update | |
fireselector = debouncer3.read(); | |
if (fireselector == LOW) // Switch closed - Fireselector == Fullauto..................................................................................................... | |
{ | |
if (trigger == LOW) // check if trigger was holded down | |
{ | |
modeVoltageProtectionEnabled =true; // still holding trigger the full time to enable Voltageprotection | |
} | |
else | |
{ | |
modeVoltageProtectionEnabled =false; // you should have released the trigger within fast motor beeps to disable | |
} | |
EEPROM.put(eeAddressVoltageProtection, modeVoltageProtectionEnabled); // safe modeVoltageProtection in EEPROM | |
}//end setup for fullauto switch - voltageprotection | |
else // Switch open - Fireselector == SEMI..................................................................................................... | |
{ | |
if (trigger == LOW) // check if trigger was holded down | |
{ | |
modePreCockingEnabled =true; // still holding trigger the full time to enable | |
} | |
else | |
{ | |
modePreCockingEnabled =false; // you should have released the trigger within fast motor beeps to disable | |
} | |
EEPROM.put(eeAddressPreCock, modePreCockingEnabled); // safe modePreCockingEnabled in EEPROM | |
}//end setup for SEMI switch - preCocking | |
for (int i=0; (i <= 180) || (trigger == LOW); i++) | |
{ | |
digitalWrite(MOSFET_PIN, HIGH); // lower noise motor vibration until trigger is released - Pleas release Trigger after hearing this noise | |
delayMicroseconds(100); | |
digitalWrite(MOSFET_PIN, LOW); | |
delayMicroseconds(2000); | |
debouncer2.update(); // check TRIGGER_PIN | |
trigger = debouncer2.read(); // write status | |
} | |
//........................................................................................................................................................................................ | |
//first programming part done. you can skip now by waiting 5s and doing nothing, or pull and hold trigger again within the 5s ............................................................ | |
for (int i=0; (i <= 50) && (trigger != LOW); i++) // needed for recognizing again the trigger pull | |
{ // second programming cycle starts now similar to first, but changing different modes now | |
debouncer2.update(); | |
trigger = debouncer2.read(); | |
delay(100); | |
} | |
if (trigger == LOW) // still hold trigger, or skip | |
{ | |
for (int i=0; i <= 20; i++) | |
{ | |
for (int u=0; u <= 30; u++) | |
{ | |
digitalWrite(MOSFET_PIN, HIGH); // fast, high noise motor vibration | |
delayMicroseconds(100); | |
digitalWrite(MOSFET_PIN, LOW); | |
delayMicroseconds(500); | |
debouncer2.update(); // second trigger update, need updated while beeping important to detect if trigger was released in this (beeping) time period | |
trigger = debouncer2.read(); // write status | |
} | |
delay(100); | |
} | |
debouncer3.update(); // first normal fireselector update | |
fireselector = debouncer3.read(); | |
if (fireselector == LOW) // Switch closed - Fireselector == Fullauto..................................................................................................... | |
{ | |
if (trigger == LOW) // check if trigger was holded down | |
{ | |
CellCount = 2.0; // still holding trigger the full time to enable CellCount == 2 LipoCells | |
} | |
else | |
{ | |
CellCount = 3.0; // you should have released the trigger within fast motor beeps enable CellCount == 3 LipoCells | |
} | |
EEPROM.put(eeAddressCellCount, CellCount); // safe modeVoltageProtection in EEPROM | |
}//end setup for fullauto switch - CellCount | |
else // Switch open - Fireselector == SEMI..................................................................................................... | |
{ | |
if (trigger == LOW) // check if trigger was holded down | |
{ | |
modeActiveBreakingEnabled =true; // still holding trigger the full time to enable | |
} | |
else | |
{ | |
modeActiveBreakingEnabled =false; // you should have released the trigger within fast motor beeps to disable | |
} | |
EEPROM.put(eeAddressActiveBreaking, modeActiveBreakingEnabled); // safe modeActiveBreakingEnabled in EEPROM | |
}//end setup for SEMI switch - activebreaking | |
for (int i=0; (i <= 180) || (trigger == LOW); i++) | |
{ | |
digitalWrite(MOSFET_PIN, HIGH); // lower noise motor vibration until trigger is released - Pleas release Trigger after hearing this noise | |
delayMicroseconds(100); | |
digitalWrite(MOSFET_PIN, LOW); | |
delayMicroseconds(2000); | |
debouncer2.update(); // check TRIGGER_PIN | |
trigger = debouncer2.read(); // write status | |
} | |
}//end second cycle of trigger programming | |
}//end trigger programming completely | |
EEPROM.get(eeAddressVoltageProtection, modeVoltageProtectionEnabled); //get all safed configurations from eeprom to variables // also if nothing has changed | |
EEPROM.get(eeAddressPreCock, modePreCockingEnabled); | |
EEPROM.get(eeAddressCellCount, CellCount); | |
EEPROM.get(eeAddressActiveBreaking, modeActiveBreakingEnabled); | |
for (int u=0; (u <= 500); u++) | |
{ | |
digitalWrite(MOSFET_PIN, HIGH); // higher noise motor vibration - ready to go on | |
delayMicroseconds(100); | |
digitalWrite(MOSFET_PIN, LOW); | |
delayMicroseconds(1000); | |
} | |
}//end setup | |
void loop() //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
{ // start switch updating | |
debouncer3.update(); // Bounce objects don’t use interrupts, so you need to update the object to check for state changes once per loop(). | |
// This method returns true (1) if the pin state just changed, and false (0) if no change was detected. | |
fireselector = debouncer3.read(); // write status to fireselector - .read Returns the updated/current pin state (1 for HIGH, 0 for LOW) | |
if (fireselector == LOW) // Switch closed - Fireselector == Fullauto........................................................................................................ | |
{ | |
debouncer2.update(); // check TRIGGER_PIN | |
trigger = debouncer2.read(); // write status | |
if (trigger == LOW) // Switch closed - Trigger pulled | |
{ | |
if (modeActiveBreakingEnabled) //(only if activeBreaking activated) | |
{ | |
digitalWrite(BREAKFET_PIN, HIGH); //remember:P-Channel Fet, HIGH means deactivate Fet (Fet stays activated since last shot) | |
} | |
digitalWrite(MOSFET_PIN, HIGH); //normal N-Channel Fet, HIGH means activate Fet | |
do { | |
debouncer2.update(); | |
trigger = debouncer2.read(); // check if trigger is still pulled | |
} | |
while (trigger == LOW); // until its released | |
timeAfterTriggerInput = millis(); // set time mark after released Trigger | |
//do // to be sure, that the gears stop every time at same position afer fullauto burst | |
// { // don't cutoff randomly after trigger release/-> wait for next cutoff cycle before switching of | |
// debouncer0.update(); // check cutoff switch | |
// cutOff = debouncer0.fell(); // debouncer.fell Returns true if the pin state just changed from HIGH to LOW, else false | |
// } | |
//while (cutOff == false && (millis() - timeAfterTriggerInput) < 130); // cutoff switch and automatic timecutoff, if no cutoff signal received after 130ms | |
// time can can be shorter than in SEMI, because of faster rotation Speed | |
// this (do-while)part can be leaved out completely if not wanted | |
// without, you can play even without cutoff switch completely fine | |
digitalWrite(MOSFET_PIN, LOW); // maybee change this part direct after trigger released without waiting for cutOff ALREADY DISABLED NOW????????????????????????????????????????????????????????????? | |
if (modeActiveBreakingEnabled) | |
{ | |
digitalWrite(BREAKFET_PIN, LOW); // P-Channel Fet: LOW means activated | |
} // activate Fet, remember P-Channel Fet will switch activated at negative Gate(LOW: PIN==GND) to Source(Vcc+) input, | |
lastshot = millis(); // start Timer for voltagecheck | |
} | |
}//endFullauto | |
else // switch open - fireselector == SEMI................................................................................................................. | |
{ | |
debouncer2.update(); // check Trigger | |
trigger = debouncer2.read(); | |
if (trigger == LOW) // Switch closed - Trigger pulled | |
{ | |
if (modeActiveBreakingEnabled) | |
{ | |
digitalWrite(BREAKFET_PIN, HIGH); //remember:P-Channel Fet, HIGH means close Fet (Fet stays open since last shot) | |
} | |
digitalWrite(MOSFET_PIN, HIGH); // normal N-Channel Fet, HIGH means open Fet | |
timeAfterTriggerInput = millis(); // set time mark after Trigger pressed | |
do | |
{ | |
debouncer0.update(); // check cutoff switch | |
cutOff = debouncer0.fell(); // debouncer.fell Returns true if the pin state just changed from HIGH to LOW, else false | |
} | |
while (cutOff == false && (millis() - timeAfterTriggerInput) < 150); // cutoff switch and automatic timecutoff, if no cutoff signal received/ if switch defect it will stop after 150ms | |
// fine tuning for each setup | |
if (modePreCockingEnabled) | |
{ // preCocking / motor pull the spring again to almost full-power-piston-position in the same cycle - faster trigger response | |
delay(preCockingTime); // Please note that pre-cocking puts a lot more stress on your gearbox. | |
} // The time in ms is individual for every battery - to high numbers cause double shots, especially, if upgrading to chihai motor | |
digitalWrite(MOSFET_PIN, LOW); // N-Channel Fet: LOW means deactivated | |
if (modeActiveBreakingEnabled) | |
{ | |
delay(activeBreakingTime); // zero or low numbers recommend or you slow down everything | |
digitalWrite(BREAKFET_PIN, LOW); // P-Channel Fet: connected to Vcc+(7,4v Lipo) LOW means activated | |
} // activate Fet, remember P-Channel Fet will switch activated at negative Gate(LOW: PIN==GND) to Source(Vcc+) input, | |
do { | |
debouncer2.update(); // check if trigger is still pulled // is this relevant???????????????????? | |
trigger = debouncer2.read(); | |
} | |
while (trigger == LOW); // wait until trigger released | |
lastshot = millis(); // start Timer for voltagecheck | |
} | |
}//end SEMI | |
//start voltage check------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
if (((millis()-lastVoltageCheck > 5000) && (millis()-lastshot > 2000) && modeVoltageProtectionEnabled) || (firstSwitchOn && modeVoltageProtectionEnabled)) | |
{ // Voltage check every 5 seconds and wait additional 2s after each shot | |
digitalVoltageread = analogRead(0); // analogue PIN Numbers are different from digital! | |
// this command "analogRead(0)" refers to _PIN 5 /P5 on DigiSpark board | |
realVoltage = (digitalVoltageread *Measured5vReference /1023.0) /voltageDivider; // calculate digital numbers to volts | |
voltagePerCell = realVoltage /CellCount ; | |
lastVoltageCheck = millis(); | |
if (firstSwitchOn) | |
{ | |
firstSwitchOn = false; // set Off, to run only once | |
for (int i=0; i <= 1; i++) | |
{ | |
for (int u=0; u <= 30; u++) | |
{ | |
digitalWrite(MOSFET_PIN, HIGH); // 2 high noise motor vibration * noise can be removed | |
delayMicroseconds(100); | |
digitalWrite(MOSFET_PIN, LOW); | |
delayMicroseconds(500); | |
} | |
delay(50); | |
} | |
} | |
if ((voltagePerCell < LOW_VOLTAGE) && modeVoltageProtectionEnabled) | |
{ | |
for (int i=0; i <= 5; i++) | |
{ | |
for (int u=0; u <= 150; u++) | |
{ | |
digitalWrite(MOSFET_PIN, HIGH); // 5 not as high noise motor vibration | |
delayMicroseconds(100); | |
digitalWrite(MOSFET_PIN, LOW); | |
delayMicroseconds(1000); | |
} | |
delay(50); | |
} | |
sleep_enable(); | |
sleep_cpu(); // BATTERY LOW -> GO SLEEP | |
} | |
}//end voltage check | |
}//end loop :) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment