Skip to content

Commit 225398d

Browse files
committed
Created
1 parent 7b78805 commit 225398d

40 files changed

+1417
-70
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ src/main.cpp
88
.DS_Store
99
.tags*
1010
tags
11+
examples/BikeSensorConverter/arduino_secrets.h

.travis.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,14 @@ cache:
3434
- "~/.platformio"
3535

3636
env:
37+
- PLATFORMIO_CI_SRC=examples/BicycleSpeedDisplay/BicycleSpeedDisplay.ino
3738
- PLATFORMIO_CI_SRC=examples/EnvironmentDisplay/EnvironmentDisplay.ino
3839
- PLATFORMIO_CI_SRC=examples/HeartRateDisplay/HeartRateDisplay.ino
3940
- PLATFORMIO_CI_SRC=examples/BicycleSpeedDisplay/BicycleSpeedDisplay.ino
4041
- PLATFORMIO_CI_SRC=examples/LEVDisplay/LEVDisplay.ino
42+
- PLATFORMIO_CI_SRC=examples/HeartRateMonitor/HeartRateMonitor.ino
43+
- PLATFORMIO_CI_SRC=examples/Shifting/Shifting.ino
44+
- PLATFORMIO_CI_SRC=examples/MuscleOxygenMonitor/MuscleOxygenMonitor.ino
4145

4246
install:
4347
- pip install -U platformio

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ See [ant-arduino](https://github.com/cujomalainey/ant-arduino#hardware)
6666

6767
## Support ANT+ Profiles
6868

69-
This library aims to support all ANT+ devices. This goal will take time but its an attainable one. Check out the [wiki](https://github.com/cujomalainey/antplus-arduino/wiki/Profile-Support) for the list of profiles implemented and their versions.
69+
This library aims to support all ANT+ devices. This goal will take time but its an attainable one. Check out the [wiki](https://github.com/cujomalainey/antplus-arduino/wiki/Profile-Support) for the list of profiles implemented and their verions.
7070

7171
## Installation
7272

@@ -76,7 +76,7 @@ Arduino 1.5 and later
7676

7777
Arduino now includes a library manager for easier library installation. From the Sketch menu select include library->Manage Libraries, then type "antplus-arduino" in the filter and install.
7878

79-
Prior to Arduino 1.5 installation is manual
79+
Prior to Arduino 1.5 installation is a manual
8080

8181
Download a .zip or .tar.gz release from github. Determine the location of your sketchbook by selecting "preferences" on the Arduino menu. Create a "libraries" folder in your sketchbook and unzip the release file in that location.
8282

Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
/**********************************************
2+
* AntPlus Bike Sensor Converter
3+
* LEV Display example
4+
* MuscleOxygen monitor
5+
* Shifting monitor
6+
*
7+
* Finds a nearby LEV Sensor, pairs
8+
* to it and then reads the information
9+
* out via the serial port.
10+
*
11+
* Author Bernd Woköck
12+
* based on the work of Curtis Malainey
13+
**********************************************/
14+
#include <Arduino.h>
15+
#include "ANT.h"
16+
#include "ANTPLUS.h"
17+
18+
// get ANT network key
19+
#include "arduino_secrets.h"
20+
21+
#define BAUD_RATE 9600
22+
23+
#define ANT_DEVICE_NUMBER_MOXY 7369
24+
#define ANT_DEVICE_NUMBER_SHIFT 7370
25+
#define CHANNEL_0 0
26+
#define CHANNEL_1 1
27+
#define CHANNEL_2 2
28+
29+
const uint8_t NETWORK_KEY[] = SECRET_ANTNETWORK_KEY;
30+
31+
AntWithCallbacks ant = AntWithCallbacks();
32+
AntPlusRouter router = AntPlusRouter();
33+
ProfileLevDisplay lev = ProfileLevDisplay();
34+
ProfileMuscleOxygenMonitor moxy = ProfileMuscleOxygenMonitor(ANT_DEVICE_NUMBER_MOXY);
35+
ProfileShiftingShifter shift = ProfileShiftingShifter(ANT_DEVICE_NUMBER_SHIFT);
36+
37+
void levBaseDataPageHandler(AntRxDataResponse& msg, uintptr_t data);
38+
void levSpeedSystemInformation1Handler(LevSpeedSystemInformation1& msg, uintptr_t data);
39+
void levSpeedDistanceInformationHandler(LevSpeedDistanceInformation& msg, uintptr_t data);
40+
void levAltSpeedDistanceInformationHandler(LevAltSpeedDistanceInformation& msg, uintptr_t data);
41+
void levSpeedSystemInformation2Handler(LevSpeedSystemInformation2& msg, uintptr_t data);
42+
void levBatteryInfo(LevBatteryInfo& msg, uintptr_t data);
43+
void levAntChannelEvent(ChannelEventResponse& msg, uintptr_t data);
44+
45+
void moxyCreateMsgHandler(MuscleOxygenBaseMainDataPageMsg& msg, uintptr_t data);
46+
47+
void shiftCreateMsgHandler(ShiftingBaseMainDataPageMsg& msg, uintptr_t data);
48+
49+
void manufacturersInformationDataPageHandler(ManufacturersInformation& msg, uintptr_t data);
50+
void productInformationDataPageHandler(ProductInformation& msg, uintptr_t data);
51+
52+
void printStatus(uint8_t status);
53+
54+
// mask for changed values
55+
enum {
56+
SPEED = 1,
57+
ODOMETER = 2,
58+
BATTERYSOC = 4,
59+
SUPPORTLEVEL = 8,
60+
SUPPORTLEVELCNT = 16,
61+
PERCENTASSIST = 32,
62+
WHEELCIRC = 64,
63+
};
64+
65+
// LEV data
66+
struct levDataST {
67+
uint32_t changedValueMask; // bit field for changed values
68+
uint16_t speed; // in 0.1km/h
69+
uint32_t odometer; // in 0.01km
70+
uint8_t batterySOC; // in percent
71+
uint8_t supportLevel; // 0..3
72+
uint8_t supportLevelCount; // 4
73+
uint8_t percentAssist; // in percent
74+
uint16_t wheelCircumference; // in mm
75+
}
76+
_levData = { 0, 0, 0, 0, 0, 0, 0, 0 };
77+
78+
void setup() {
79+
Serial2.begin(BAUD_RATE);
80+
ant.setSerial(Serial2);
81+
delay(1000);
82+
83+
router.setDriver(&ant); // never touch ant again
84+
router.setAntPlusNetworkKey(NETWORK_KEY);
85+
router.setProfile(CHANNEL_0, &lev);
86+
router.setProfile(CHANNEL_1, &moxy);
87+
router.setProfile(CHANNEL_2, &shift);
88+
// Delay after initial setup to wait for user to connect on serial
89+
90+
Serial.begin(BAUD_RATE);
91+
Serial.println("Running");
92+
93+
// setup lev display
94+
lev.onDataPage(levBaseDataPageHandler);
95+
lev.onLevSpeedSystemInformation1(levSpeedSystemInformation1Handler);
96+
lev.onLevSpeedDistanceInformation(levSpeedDistanceInformationHandler);
97+
lev.onLevAltSpeedDistanceInformation(levAltSpeedDistanceInformationHandler);
98+
lev.onLevSpeedSystemInformation2(levSpeedSystemInformation2Handler);
99+
lev.onLevBatteryInfo(levBatteryInfo);
100+
lev.onLevCapabilities(levCapabilities);
101+
lev.onManufacturersInformation(manufacturersInformationDataPageHandler);
102+
lev.onProductInformation(productInformationDataPageHandler);
103+
lev.onChannelEvent(levAntChannelEvent);
104+
lev.begin();
105+
delay(500); // wait for module initialization
106+
107+
// setup muscle oxygen monitor
108+
moxy.createMuscleOxygenDataMsg(moxyCreateMsgHandler);
109+
moxy.begin();
110+
delay(500);
111+
112+
// setup shifting oxygen monitor
113+
shift.createShiftingDataMsg(shiftCreateMsgHandler);
114+
shift.begin();
115+
delay(500);
116+
117+
// uint8_t status = lev.waitForPair(); // todo no busy wait here
118+
}
119+
120+
void loop() {
121+
router.loop();
122+
}
123+
124+
void levAntChannelEvent(ChannelEventResponse& msg, uintptr_t data) {
125+
if (msg.getCode() == STATUS_EVENT_CHANNEL_CLOSED)
126+
{
127+
Serial.println("channel closed - reconnect");
128+
lev.begin();
129+
}
130+
}
131+
132+
void levBaseDataPageHandler(AntRxDataResponse& msg, uintptr_t data) {
133+
LevBaseMainDataPage dp = LevBaseMainDataPage(msg);
134+
Serial.println("===========================");
135+
Serial.print("DataPage: ");
136+
Serial.println(dp.getDataPageNumber());
137+
}
138+
139+
void levSpeedSystemInformation1Handler(LevSpeedSystemInformation1& msg, uintptr_t data) {
140+
_levData.speed = msg.getSpeed();
141+
_levData.supportLevel = decodeSupportLevel(msg.getTravelModeState());
142+
_levData.changedValueMask |= SPEED | SUPPORTLEVEL;
143+
144+
Serial.print("Temperature state: ");
145+
Serial.println(msg.getTemperatureState()); // TODO enums for temperature state
146+
Serial.print("Travel mode state: ");
147+
Serial.println(msg.getTravelModeState()); // TODO decode travel mode state
148+
Serial.print("System state: ");
149+
Serial.println(msg.getSystemState()); // TODO enums for system state
150+
Serial.print("Gear state: ");
151+
Serial.println(msg.getGearState()); // TODO decode gear state
152+
Serial.print("Gear error: ");
153+
Serial.println(msg.getErrorMessage()); // TODO enums for error message
154+
Serial.print("Speed: ");
155+
Serial.print(msg.getSpeed() / 10);
156+
Serial.print(".");
157+
Serial.println(msg.getSpeed() % 10);
158+
}
159+
160+
void levSpeedDistanceInformationHandler(LevSpeedDistanceInformation& msg, uintptr_t data) {
161+
_levData.odometer = msg.getOdometer();
162+
_levData.speed = msg.getSpeed();
163+
_levData.changedValueMask |= SPEED | ODOMETER;
164+
165+
Serial.print("Odometer: ");
166+
Serial.println((float)msg.getOdometer() / 100);
167+
Serial.print("Remaining range: ");
168+
Serial.println(msg.getRemainingRange()); // TODO 0 = unknown
169+
Serial.print("Speed: ");
170+
Serial.print(msg.getSpeed() / 10);
171+
Serial.print(".");
172+
Serial.println(msg.getSpeed() % 10);
173+
}
174+
175+
void levAltSpeedDistanceInformationHandler(LevAltSpeedDistanceInformation& msg, uintptr_t data) {
176+
_levData.odometer = msg.getOdometer();
177+
_levData.speed = msg.getSpeed();
178+
_levData.changedValueMask |= SPEED | ODOMETER;
179+
180+
Serial.print("Total dist: ");
181+
Serial.println((float)msg.getOdometer() / 100);
182+
Serial.print("Fuel consumption: ");
183+
Serial.println(msg.getFuelConsumption()); // TODO 0 = unknown
184+
Serial.print("Speed: ");
185+
Serial.print(msg.getSpeed() / 10);
186+
Serial.print(".");
187+
Serial.println(msg.getSpeed() % 10);
188+
}
189+
190+
void levSpeedSystemInformation2Handler(LevSpeedSystemInformation2& msg, uintptr_t data) {
191+
_levData.batterySOC = msg.getBatterySOC();
192+
_levData.supportLevel = decodeSupportLevel(msg.getTravelModeState());
193+
_levData.percentAssist = msg.getPercentAssist();
194+
_levData.speed = msg.getSpeed();
195+
_levData.changedValueMask |= BATTERYSOC | SUPPORTLEVEL| PERCENTASSIST| SPEED;
196+
197+
Serial.print("Battery SOC: ");
198+
Serial.println(msg.getBatterySOC());
199+
Serial.print("Travel mode state: ");
200+
Serial.println(msg.getTravelModeState()); // TODO decode travel mode state
201+
Serial.print("System state: ");
202+
Serial.println(msg.getSystemState()); // TODO enums for system state
203+
Serial.print("Gear state: ");
204+
Serial.println(msg.getGearState()); // TODO decode gear state
205+
Serial.print("Percent Assist: ");
206+
Serial.println(msg.getPercentAssist());
207+
Serial.print("Speed: ");
208+
Serial.print(msg.getSpeed() / 10);
209+
Serial.print(".");
210+
Serial.println(msg.getSpeed() % 10);
211+
}
212+
213+
void levBatteryInfo(LevBatteryInfo& msg, uintptr_t data) {
214+
Serial.print("Charging Cycle Count: ");
215+
Serial.println(msg.getChargingCycleCount());
216+
Serial.print("Fuel consumption: ");
217+
Serial.println(msg.getFuelConsumption());
218+
Serial.print("Battery voltage: ");
219+
Serial.println(msg.getBatteryVoltage());
220+
Serial.print("Distance on current charge: ");
221+
Serial.println(msg.getDistanceOnCurrentCharge());
222+
}
223+
224+
void levCapabilities(LevCapabilities& msg, uintptr_t data) {
225+
_levData.wheelCircumference = msg.getWheelCircumference(); // in mm
226+
_levData.supportLevelCount = 4; // (msg.getTravelModesSupported() >> 3) & 0x07; // 4
227+
_levData.changedValueMask |= WHEELCIRC | SUPPORTLEVELCNT;
228+
229+
Serial.print("Travel modes supported: ");
230+
Serial.println(msg.getTravelModesSupported());
231+
Serial.print("Wheel circumference: ");
232+
Serial.println(msg.getWheelCircumference());
233+
}
234+
235+
void manufacturersInformationDataPageHandler(ManufacturersInformation& msg, uintptr_t data) {
236+
Serial.print("DataPage: ");
237+
Serial.println(msg.getDataPageNumber());
238+
Serial.print("HW Revision: ");
239+
Serial.println(msg.getHWRevision());
240+
Serial.print("ManufacturerID: ");
241+
Serial.println(msg.getManufacturerID());
242+
Serial.print("Model Number: ");
243+
Serial.println(msg.getModelNumber());
244+
}
245+
246+
void productInformationDataPageHandler(ProductInformation& msg, uintptr_t data) {
247+
Serial.print("DataPage: ");
248+
Serial.println(msg.getDataPageNumber());
249+
Serial.print("SW Revision Supplemental: ");
250+
Serial.println(msg.getSWRevisionSupplemental());
251+
Serial.print("SW Revision Main: ");
252+
Serial.println(msg.getSWRevisionMain());
253+
Serial.print("Serial Number: ");
254+
Serial.println(msg.getSerialNumber());
255+
}
256+
257+
void moxyCreateMsgHandler(MuscleOxygenBaseMainDataPageMsg& msg, uintptr_t data)
258+
{
259+
static uint8_t _eventCnt = 0;
260+
/* value mapping
261+
batterySOC --> CurrentSaturatedHemoglobinPercentage
262+
supportlevel.percentAssist --> TotalHemoglobinConcentration
263+
*/
264+
265+
if (_levData.changedValueMask & (BATTERYSOC | SUPPORTLEVEL | PERCENTASSIST)) {
266+
_levData.changedValueMask &= ~(BATTERYSOC | SUPPORTLEVEL | PERCENTASSIST);
267+
_eventCnt++;
268+
}
269+
msg.setCurrentSaturatedHemoglobinPercentage(_levData.batterySOC * 10 + _eventCnt % 2); // in 0.1 % (0 - 100)-- > 0 - 1000
270+
msg.setTotalHemoglobinConcentration(_levData.supportLevel * 100 + min(99, _levData.percentAssist)); // in 0.01g/dl (0-40) --> 0-4000
271+
msg.setEventCount(_eventCnt);
272+
Serial.println("new moxy values--------------");
273+
}
274+
275+
void shiftCreateMsgHandler(ShiftingBaseMainDataPageMsg& msg, uintptr_t data)
276+
{
277+
static uint8_t _eventCnt = 0;
278+
279+
/* value mapping
280+
supportLevelCount (3) --> TotalNumbersGearFront
281+
10 --> TotalNumbersGearRear
282+
supportLevel (1-3) --> CurrentGearFront
283+
percentAssist/10 --> CurrentGearRear
284+
*/
285+
286+
if (_levData.changedValueMask & (SUPPORTLEVELCNT | SUPPORTLEVEL | PERCENTASSIST)) {
287+
_levData.changedValueMask &= ~(SUPPORTLEVELCNT | SUPPORTLEVEL | PERCENTASSIST);
288+
_eventCnt++;
289+
}
290+
msg.setTotalNumbersGearFront(3);
291+
msg.setTotalNumbersGearRear(10);
292+
msg.setCurrentGearFront(_levData.supportLevel-1);
293+
msg.setCurrentGearRear(10 - (_levData.percentAssist / 10));
294+
msg.setEventCount(_eventCnt);
295+
Serial.println("new shifting values---------------");
296+
}
297+
298+
299+
uint8_t decodeSupportLevel(uint8_t inValue) {
300+
const uint8_t slConv[] = {0,1,1,2,2,3,3,4,4}; // specialized: 0,1,3,5
301+
uint8_t sl = slConv[((inValue >> 3) & 0x07)];
302+
return sl;
303+
}
304+
305+
void printStatus(uint8_t status) {
306+
Serial.print("Channel Status: ");
307+
switch (status) {
308+
case CHANNEL_STATUS_UNASSIGNED:
309+
Serial.println("Unassigned");
310+
break;
311+
case CHANNEL_STATUS_ASSIGNED:
312+
Serial.println("Assigned");
313+
break;
314+
case CHANNEL_STATUS_SEARCHING:
315+
Serial.println("Searching");
316+
break;
317+
case CHANNEL_STATUS_TRACKING:
318+
Serial.println("Tracking");
319+
break;
320+
}
321+
}

0 commit comments

Comments
 (0)