├── README.md ├── esp-12-smart-button-w-ultra-low-standby-power.png ├── esp-12-smart-button-w-ultra-low-standby-power.sch ├── pushingbox_smart_buton - arduino sketch └── pushingbox_smart_buton.ino └── smart_button_ulsp_core_sch.png /README.md: -------------------------------------------------------------------------------- 1 | ## (Pushingbox) Smart button w/ Ultra Low Standby Power <1µA 2 | 3 | 4 | -------------------------------------------------------------------------------- /esp-12-smart-button-w-ultra-low-standby-power.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8n1/esp8266-smart-button/ac55956803a3f1e91e775fdda7ce4f11f3eb0a82/esp-12-smart-button-w-ultra-low-standby-power.png -------------------------------------------------------------------------------- /pushingbox_smart_buton - arduino sketch/pushingbox_smart_buton.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: (Pushingbox) Smart button with ultra low standby power 3 | * Version: 0.9 4 | * Date: 27. Apr, 2016 5 | * 6 | * Description: 7 | * -- Sets the pin 'power_pin' to HIGH (this keeps the ldo enabled) 8 | * - Measures the battery voltage 9 | * -> If the voltage is lower then 'undervoltage' volts, signal a recharge (see Blink Codes) and shut down. 10 | * -> If the voltage is higher, connects to the given access point and proceeds... 11 | * - Collects some more data (wifi signal strength, ip address, time to get the ip) 12 | * - Launches the given Pushingbox scenario and sends the colleted data(variables) with it 13 | * -- Sets the 'power_pin' pin to LOW (this causes the ldo to shut down) 14 | * 15 | * Configuration: 16 | * Most important (MUST be configured): Wifi(ssid, password) and Pushingbox(devid) config 17 | * May needs to be configured: vref, undervoltage 18 | * The other variables can be left unchanged 19 | * 20 | * Used pushingbox variables: 21 | * $rssi$ = Wifi signal strength in dBm (example: "-59") 22 | * $ip$ = The ip address (example: "192.168.0.45") 23 | * $ip_time$ = The time it took to get the ip in seconds ("3.4") 24 | * $vbat$ = Measured battery voltage ("3.86") 25 | * 26 | * Status LED Blink Codes: 27 | * 2x green = GET reqeust successfully sent (scenario launched) 28 | * 2x red = GET request failed 29 | * 3x red = Could not connect to the wifi (wrong password or wifi network not in range) 30 | * 1x red = Battery empty. Time to reacharge. 31 | * 32 | * TODO: 33 | * Pushingbox request error handling - #131 34 | * Fix ugly ip_time formating - #166 35 | */ 36 | 37 | 38 | // Wifi config 39 | const char* ssid = "xxxxx"; 40 | const char* password = "xxxxx"; 41 | 42 | // Pushingbox config 43 | // Device id of the pushingbox scenario to launch 44 | const char* devid = "xxxxx"; 45 | 46 | 47 | // Power/Shutdown pin 48 | const int power_pin = 2; 49 | 50 | // Status leds 51 | const int ok_led = 12; 52 | const int error_led = 14; 53 | const int act_led = 13; 54 | 55 | // Activity led blink speed in seconds 56 | const float blink_speed = 0.4; 57 | 58 | // Voltage divider config 59 | const int r1 = 4700; 60 | const int r2 = 1000; 61 | // Acutal adc reference voltage (turns out it isn't exactly 1.0V) 62 | const float vref = 0.975; 63 | 64 | // Undervoltage detection (can be set to 0 if not needed) 65 | // If the measured voltage is lower then 'undervoltage' volts, signal a recharge and shut down 66 | const float undervoltage = 3.0; 67 | 68 | // Seconds to wait for a ip before giving up and shutting down 69 | const int wifi_timeout = 15; 70 | 71 | 72 | #include 73 | #include 74 | 75 | Ticker act_led_flipper; 76 | 77 | int rssi; 78 | unsigned long ip_time; 79 | float vcc; 80 | IPAddress ip_address; 81 | 82 | void connect_to_wifi() 83 | { 84 | // connect to the given ssid 85 | WiFi.begin(ssid, password); 86 | 87 | // wait for a ip from DHCP 88 | unsigned long timeout = millis(); 89 | while (WiFi.status() != WL_CONNECTED) { 90 | // but not longer then "wifi_timout" seconds 91 | if (millis() - timeout > wifi_timeout * 1000) { 92 | Serial.print("\n-> Could not connect to ap: "); 93 | Serial.println(ssid); 94 | // shut down 95 | shutdown(1, 5); 96 | } 97 | Serial.print("."); 98 | delay(500); 99 | } 100 | ip_time = millis(); 101 | 102 | // get the wifi signal strength: 103 | rssi = WiFi.RSSI(); 104 | // save the ip address 105 | ip_address = WiFi.localIP(); 106 | 107 | Serial.println(""); 108 | Serial.println("-> Connected."); 109 | Serial.print(" IP: "); 110 | Serial.print(ip_address); 111 | Serial.printf(" (%i.%is)\n", millis() / 1000, millis() % 1000); 112 | Serial.print(" RSSI:"); 113 | Serial.print(rssi); 114 | Serial.println("dBm\n"); 115 | Serial.println(""); 116 | } 117 | 118 | void send_pushingbox_request() 119 | { 120 | // combine all variables into a single string 121 | String request_uri = ""; 122 | 123 | // add the signal strength 124 | request_uri += "&rssi="; 125 | request_uri += rssi; 126 | 127 | // add the ip address 128 | String ip = String(ip_address[0]) + "." + String(ip_address[1]) + "." + String(ip_address[2]) + "." + String(ip_address[3]); 129 | request_uri += "&ip="; 130 | request_uri += ip; 131 | 132 | // add the time it took to get the ip 133 | // TODO: fix ugly formating (example: in:3450; out=3.4) 134 | String formated_ip_time; 135 | formated_ip_time = ip_time / 1000; 136 | formated_ip_time += "\."; 137 | String temp; 138 | temp = String(ip_time % 1000); 139 | temp = temp.substring(0, 1); 140 | formated_ip_time += temp; 141 | request_uri += "&ip_time="; 142 | request_uri += formated_ip_time; 143 | 144 | // add the battery voltage 145 | request_uri += "&vcc="; 146 | request_uri += vcc; 147 | 148 | // print the final query string 149 | Serial.print("Request: "); 150 | Serial.println(request_uri); 151 | 152 | // create the http connection 153 | WiFiClient client; 154 | if (!client.connect("api.pushingbox.com", 80)) { 155 | Serial.println("-> Connection failed"); 156 | shutdown(1, 3); 157 | return; 158 | } 159 | Serial.println("-> Done."); 160 | 161 | // if connected, send the GET request 162 | Serial.println("Sending request"); 163 | client.print(String("GET /pushingbox?devid=") + devid + request_uri + " HTTP/1.1\r\n" + 164 | "Host: api.pushingbox.com\r\n" + 165 | "Connection: close\r\n\r\n"); 166 | 167 | // print all lines from the response - TODO 168 | while (client.available()) { 169 | String line = client.readStringUntil('\r'); 170 | Serial.print(line); 171 | } 172 | Serial.println("-> Done. Connection closed.\n"); 173 | } 174 | 175 | void shutdown(boolean error, int blink_count) 176 | { 177 | // stop the activity led 178 | act_led_flipper.detach(); 179 | digitalWrite(act_led, LOW); 180 | 181 | // either blink the 'error' or 'ok' led, depending on if something went wrong 182 | int led_to_blink; 183 | if (error == 0) { 184 | led_to_blink = ok_led; 185 | } 186 | else if (error == 1) { 187 | led_to_blink = error_led; 188 | } 189 | // blink the led 'blink_count' times 190 | for (int i = 0; i < blink_count; i++) 191 | { 192 | digitalWrite(led_to_blink, HIGH); 193 | delay(200); 194 | digitalWrite(led_to_blink, LOW); 195 | if (i < blink_count - 1) 196 | delay(200); 197 | } 198 | 199 | // shutdown the voltage regualtor by "releasing" the ldo enable pin 200 | Serial.printf(" Time elapsed: %i.%i Seconds\n", millis() / 1000, millis() % 1000); 201 | Serial.println(" Shutting down..."); 202 | digitalWrite(power_pin, LOW); 203 | // also activate regular deepsleep so the sketch can be used without the enable pin shutdown circuit 204 | //ESP.deepSleep(0, WAKE_RF_DEFAULT); 205 | delay(500); 206 | } 207 | 208 | void toogle_act_led() 209 | { 210 | digitalWrite(act_led, !digitalRead(act_led)); 211 | } 212 | 213 | float get_battery_voltage() 214 | { 215 | // read raw adc value (0-1023) 216 | int adc_value = analogRead(0); 217 | 218 | // calc input voltage (0-1V) 219 | float battery_voltage = vref / 1024.0 * adc_value; 220 | 221 | // calc battery voltage (0 - ~5.5V) 222 | battery_voltage = battery_voltage * (r1 + r2) / r2; 223 | 224 | return battery_voltage; 225 | } 226 | 227 | void setup() 228 | { 229 | // Hold the ldo enable pin HIGH 230 | pinMode(power_pin, OUTPUT); 231 | digitalWrite(power_pin, HIGH); 232 | 233 | // Init led pins 234 | pinMode(ok_led, OUTPUT); 235 | pinMode(error_led , OUTPUT); 236 | pinMode(act_led, OUTPUT); 237 | 238 | // Start blinking the activity led 239 | act_led_flipper.attach(blink_speed, toogle_act_led); 240 | 241 | // Setup the serial port 242 | Serial.begin(115200); 243 | Serial.println(""); 244 | 245 | // Get the battery voltage 246 | vcc = get_battery_voltage(); 247 | // Check for undervoltage 248 | if (vcc < undervoltage) 249 | { 250 | Serial.println(" Battery voltage ciritical!"); 251 | Serial.println(" Recharge!"); 252 | Serial.print(" Voltage: "); 253 | Serial.print(vcc); 254 | Serial.println("V\n"); 255 | 256 | WiFi.disconnect(); 257 | shutdown(1, 1); 258 | } 259 | 260 | // Connect to the wifi network 261 | Serial.print("Connecting to access point: "); 262 | Serial.println(ssid); 263 | connect_to_wifi(); 264 | 265 | // Send the Pushingbox request 266 | Serial.print("Connecting to "); 267 | Serial.println("api.pushingbox.com"); 268 | send_pushingbox_request(); 269 | 270 | // Shutdown 271 | shutdown(0, 2); 272 | } 273 | 274 | void loop() 275 | { 276 | // nothing in here 277 | } 278 | 279 | -------------------------------------------------------------------------------- /smart_button_ulsp_core_sch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8n1/esp8266-smart-button/ac55956803a3f1e91e775fdda7ce4f11f3eb0a82/smart_button_ulsp_core_sch.png --------------------------------------------------------------------------------