├── 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
--------------------------------------------------------------------------------