Skip to content

Commit c6648e5

Browse files
committed
Add new Power Control example
1 parent 07799cf commit c6648e5

File tree

1 file changed

+163
-0
lines changed

1 file changed

+163
-0
lines changed
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
//
2+
// Copyright 2022 Blues Inc. All rights reserved.
3+
// Use of this source code is governed by licenses granted by the
4+
// copyright holder including that found in the LICENSE file.
5+
//
6+
// This example contains the complete source for the Sensor Tutorial at dev.blues.io
7+
// https://dev.blues.io/build/tutorials/sensor-tutorial/notecarrier-af/esp32/arduino-wiring/
8+
//
9+
// This tutorial requires a Notecarrier-F (or equivalently-wired carrier board) designed
10+
// enable the Notecard's ATTN pin to control a host MCU's power supply.
11+
//
12+
13+
#include <Notecard.h>
14+
#include <Wire.h>
15+
16+
// Parameters for this example
17+
#define notehubProductUID "com.your_company.your_name:your_project" // if you're your_name@your_company.com
18+
#define notehubUploadPeriodMins 10
19+
#define hostSleepSeconds 60
20+
21+
// Arduino serial debug monitor port definitions
22+
#define serialDebug Serial
23+
24+
// Notecard I2C port definitions
25+
Notecard notecard;
26+
27+
// When the Notecard puts the host MCU to sleep, it enables the host to save 'state' inside the
28+
// notecard while it's asleep, and to retrieve this state when it awakens. These are several
29+
// 'segments' of state that may individually be saved.
30+
struct {
31+
int cycles;
32+
} globalState;
33+
const char globalSegmentID[] = "GLOB";
34+
35+
struct {
36+
int measurements;
37+
} tempSensorState;
38+
const char tempSensorSegmentID[] = "TEMP";
39+
40+
struct {
41+
int measurements;
42+
} voltSensorState;
43+
const char voltSensorSegmentID[] = "VOLT";
44+
45+
// One-time Arduino initialization
46+
void setup()
47+
{
48+
49+
// Arduino IDE requires a delay to move the serial port over
50+
// from programming the MCU to the debug monitor.
51+
delay(2500);
52+
serialDebug.begin(115200);
53+
notecard.setDebugOutputStream(serialDebug);
54+
55+
// Initialize the physical I2C I/O channel to the Notecard
56+
Wire.begin();
57+
notecard.begin();
58+
59+
// Determine whether or not this is a 'clean boot', or if we're
60+
// restarting after having been put to sleep by the Notecard.
61+
NotePayloadDesc payload;
62+
bool retrieved = NotePayloadRetrieveAfterSleep(&payload);
63+
64+
// If the payload was successfully retrieved, attempt to restore state from the payload
65+
if (retrieved) {
66+
67+
// Restore the various state data structures
68+
retrieved &= NotePayloadGetSegment(&payload, globalSegmentID, &globalState, sizeof(globalState));
69+
retrieved &= NotePayloadGetSegment(&payload, tempSensorSegmentID, &tempSensorState, sizeof(tempSensorState));
70+
retrieved &= NotePayloadGetSegment(&payload, voltSensorSegmentID, &voltSensorState, sizeof(voltSensorState));
71+
72+
// We're done with the payload, so we can free it
73+
NotePayloadFree(&payload);
74+
75+
}
76+
77+
// If this is our first time through, initialize the Notecard and state
78+
if (!retrieved) {
79+
80+
// Initialize operating state
81+
memset(&globalState, 0, sizeof(globalState));
82+
memset(&tempSensorState, 0, sizeof(tempSensorState));
83+
memset(&voltSensorState, 0, sizeof(voltSensorState));
84+
85+
// Initialize the Notecard
86+
J *req = NoteNewRequest("hub.set");
87+
JAddStringToObject(req, "product", notehubProductUID);
88+
JAddStringToObject(req, "mode", "periodic");
89+
JAddNumberToObject(req, "outbound", notehubUploadPeriodMins);
90+
NoteRequest(req);
91+
92+
// Because many devs will be using oscilloscopes or joulescopes to closely examine power
93+
// consumption, it can be helpful during development to provide a stable and repeatable
94+
// power consumption environment. In the Notecard's default configuration, the
95+
// accelerometer is 'on'. As such, when debugging, devs may see tiny little blips from
96+
// time to time on the scope. These little blips are caused by accelerometer interrupt
97+
// processing, when developers accidentally tap the notecard or carrier. As such,
98+
// to help during development and measurement, this request disables the accelerometer.
99+
req = NoteNewRequest("card.motion.mode");
100+
JAddBoolToObject(req, "stop", true);
101+
NoteRequest(req);
102+
103+
}
104+
105+
}
106+
107+
void loop()
108+
{
109+
110+
// Bump the number of cycles
111+
globalState.cycles++;
112+
113+
// Simulation of a device taking a measurement of a temperature sensor. Because we
114+
// don't have an actual external hardware sensor in this example, we're just retrieving
115+
// the internal surface temperature of the Notecard.
116+
double currentTemperature = 0.0;
117+
J *rsp = NoteRequestResponse(NoteNewRequest("card.temp"));
118+
if (rsp != NULL) {
119+
currentTemperature = JGetNumber(rsp, "value");
120+
NoteDeleteResponse(rsp);
121+
tempSensorState.measurements++;
122+
}
123+
124+
// Simulation of a device taking a measurement of a voltage sensor. Because we
125+
// don't have an actual external hardware sensor in this example, we're just retrieving
126+
// the battery voltage being supplied to the Notecard.
127+
double currentVoltage = 0.0;
128+
rsp = NoteRequestResponse(NoteNewRequest("card.voltage"));
129+
if (rsp != NULL) {
130+
currentVoltage = JGetNumber(rsp, "value");
131+
NoteDeleteResponse(rsp);
132+
voltSensorState.measurements++;
133+
}
134+
135+
// Add a note to the Notecard containing the sensor readings
136+
J *req = NoteNewRequest("note.add");
137+
if (req != NULL) {
138+
JAddStringToObject(req, "file", "example.qo");
139+
J *body = JCreateObject();
140+
if (body != NULL) {
141+
JAddNumberToObject(body, "cycles", globalState.cycles);
142+
JAddNumberToObject(body, "temperature", currentTemperature);
143+
JAddNumberToObject(body, "temperature_measurements", tempSensorState.measurements);
144+
JAddNumberToObject(body, "voltage", currentVoltage);
145+
JAddNumberToObject(body, "voltage_measurements", voltSensorState.measurements);
146+
JAddItemToObject(req, "body", body);
147+
}
148+
NoteRequest(req);
149+
}
150+
151+
// Put ourselves back to sleep for a fixed period of time
152+
NotePayloadDesc payload = {0, 0, 0};
153+
NotePayloadAddSegment(&payload, globalSegmentID, &globalState, sizeof(globalState));
154+
NotePayloadAddSegment(&payload, voltSensorSegmentID, &voltSensorState, sizeof(voltSensorState));
155+
NotePayloadAddSegment(&payload, tempSensorSegmentID, &tempSensorState, sizeof(tempSensorState));
156+
NotePayloadSaveAndSleep(&payload, hostSleepSeconds, NULL);
157+
158+
// We should never return here, because the Notecard put us to sleep. If we do
159+
// get here, it's because the Notecarrier was configured to supply power to this
160+
// host MCU without being switched by the ATTN pin.
161+
delay(15000);
162+
163+
}

0 commit comments

Comments
 (0)