Writing BLE to Cycling Control Point - Adding Resistance - dart

I have bee working with BLE for a while now, but primarily for reading and notifying characteristics.
The devices specifically are Virtual cycle trainers that support GATTS Cycling Power Service - 0x1818 link
I know that it's possible to increase resistance on this trainer, but I have read the documentation on Cycling Power Control Point - 0x2A66 [link][2] which is the only one with Mandatory write functions, but non of the documentation seem to be make sense.
Trainer: Cycleops Magnus
Reading and writing characteristic
// Reads all characteristics
var characteristics = service.characteristics;
for(BluetoothCharacteristic c in characteristics) {
List<int> value = await device.readCharacteristic(c);
print(value);
}
// Writes to a characteristic
await device.writeCharacteristic(c, [0x12, 0x34])
Reading and writing descriptors
// Reads all descriptors
var descriptors = characteristic.descriptors;
for(BluetoothDescriptor d in descriptors) {
List<int> value = await device.readDescriptor(d);
print(value);
}
// Writes to a descriptor
await device.writeDescriptor(d, [0x12, 0x34])
The closest I can see is setting the crank length, or chain weight but at this stage I am only guessing and am looking for some guidance.
The questions is this..
What characteristic or descriptor should I use to adjust Virtual Power
trainer resistance and what is the best way to do this?
Any coding Language is fine, I can transpose it.
Screenshot of services available for device
[2]: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.cycling_power_control_point.xml

I think you're using the wrong Bluetooth service for this. The Cycling Power Service is for collecting data from cycling power meters like this one: https://www.cyclist.co.uk/reviews/6705/long-term-review-fsa-powerbox-carbon-power-cranks
For your requirements, I believe you should be using the Fitness Machine Service (0x1826) which includes the Indoor Bike Data characteristic (0x2AD2) and most importantly for you, the Fitness Machine Control Point characteristic. Take a look at section 4.16.1 of the Fitness Machine Service specification and you'll see details of operations which the control point supports, including a reference to 4.16.2.5 Set Target Resistance Level Procedure. I think this is what you need.

You cannot use cycling control point(CPP) for adding resistance. CPP can only be used to copy data like wheel Revolution from old peripheral to new one or if you want to reset data on peripheral you can use cpp.
If you want to add resistance you need to check for fitness machine i am using elite and elite have Fitness Machine Control point you can write resistance and other things like inclination, elevation etc using FTCP.
Few of the vendor support fitness machine and other have given their api or source code you can use that to add resistance and other stuff like that.

Indoor trainers have a few services:
Cycling Power Service (ANT+ or BT also have)
ANT+FEC (ANT only)
BTLE Fitness control (FTMS)
TACX ANT+ FEC. over Bluetooth (https://blog.lazerwalker.com/2019/02/15/bike-game-part-2.html)
Wahoo's Extension to the Cycling Power Service (to be able to set Target power for instance)
To Add Resistance to the trainer to #1, you need to check if it also has the #5 service as well. (this is the UUID used - A026E005-0A7D-4AB3-97FA-F1500F9FEB8B)
#4 is actually a protocol which Tacx came up w/ before FTMS was a standard and some trainers still use this.

Related

APPSCRIPT URL PARSING ISSUE

Ive been looking for a api to fetch if a vehicle has a open recall. I was able to find the url to pass the vin number to chrylser and receive the info I need using url fetch. I am having a issue parsing out the retreived data though.
the request is to this address:
https://www.mopar.com/moparsvc/recallInfo?vin=1C4RJKBG4M8122507&mrkt=ca&language=en_ca&campaign_status=All&campaign_type=A&callback=showVinInfo&_=1637770607999
the output data looks like this:
showVinInfo({"vin_recall":[{"vin_status":"success","campaign_status":"success","last_system_update_date":"2021-11-24","vehicle":{"vin":"1C4RJKBG4M8122507","niv":"","vehicle_desc":"JEEP GRAND CHEROKEE L LIMITED 4X4","model_year":"2021"},"recall_details":{"recall":[{"fca_campaign_number":"Y67","agency_campaign_number":"2021-576","campaign_desc":"2021 WL Radio Software Update","owner_letter_url":"/webselfservice/pdf/ca_en/Y67.pdf","type_of_campaign":"SAFETY","vin_live_date":"2021-09-23","vin_campaign_status":"REPAIRED","condition_and_risk":"Vehicles may fail to conform to Canada Motor Vehicle Safety Standard (CMVSS) 111 - Mirrors and Rear Visibility Systems. Suspect vehicles may not display the rear view image during a backing event. The vehicle operator will notice that the rearview image is not displayed if attempting to reference the image while backing. If this warning is not heeded, backing without verifying it is safe to do so could lead to an increased risk of injury to people outside the vehicle.","repair_description":"Your dealer will inspect and if necessary, update the radio software version","agency_report_date":"2021-09-21","repair_date":"2021-09-24"},{"fca_campaign_number":"Y79","agency_campaign_number":"2021-690","campaign_desc":"2021 WL & 2022 WS - ORC DTC/warning lamp","owner_letter_url":"/webselfservice/pdf/ca_en/Y79.pdf","type_of_campaign":"SAFETY","vin_live_date":"2021-11-19","vin_campaign_status":"Incomplete but repair parts are available","condition_and_risk":"The Occupant Restraint Control (ORC) module on your vehicle may have the incorrect software. The airbag warning indicator may not illuminate to notify the operator of possible compromised airbag system functionality. If specific ORC internal faults are active, then a diagnostic trouble code (DTC) will not be set and the airbag warning indicator may not illuminate. The internal faults will disable deployment of both the driver and passenger airbag squib (related to airbag venting post deployment) and knee airbags. Reduced occupant protection in the event of a crash may result in an increased risk of injury to motor vehicle occupants.","repair_description":"Your dealer will reprogram the ORC module with correct software. The estimated repair time is about a half hour.","agency_report_date":"2021-11-10","repair_date":"9999-01-01"}]}}]})
for some reason i am getting SyntaxError: Unexpected token s in JSON at position 0
*** HERE IS MY CODE WITH ATTEMPT TO FIX****
function pullOpenRecall() {
var vin = ("2C4RC1GG8LR137995");
var results = UrlFetchApp.fetch("https://www.mopar.com/moparsvc/recallInfo?vin="+vin+"&mrkt=us&language=en_us&campaign_status=All&campaign_type=A&callback=showVinInfo&_=1638229674507").getContentText();
const content = outputSample();
const json = JSON.parse(content.match(/^.+?\(({.*})\)$/)[1]);
console.log(json);
function outputSample() {
return `showVinInfo({"vin_recall":[{"vin_status":"success","campaign_status":"success","last_system_update_date":"2021-11-24","vehicle":{"vin":"1C4RJKBG4M8122507","niv":"","vehicle_desc":"JEEP GRAND CHEROKEE L LIMITED 4X4","model_year":"2021"},"recall_details":{"recall":[{"fca_campaign_number":"Y67","agency_campaign_number":"2021-576","campaign_desc":"2021 WL Radio Software Update","owner_letter_url":"/webselfservice/pdf/ca_en/Y67.pdf","type_of_campaign":"SAFETY","vin_live_date":"2021-09-23","vin_campaign_status":"REPAIRED","condition_and_risk":"Vehicles may fail to conform to Canada Motor Vehicle Safety Standard (CMVSS) 111 - Mirrors and Rear Visibility Systems. Suspect vehicles may not display the rear view image during a backing event. The vehicle operator will notice that the rearview image is not displayed if attempting to reference the image while backing. If this warning is not heeded, backing without verifying it is safe to do so could lead to an increased risk of injury to people outside the vehicle.","repair_description":"Your dealer will inspect and if necessary, update the radio software version","agency_report_date":"2021-09-21","repair_date":"2021-09-24"},{"fca_campaign_number":"Y79","agency_campaign_number":"2021-690","campaign_desc":"2021 WL & 2022 WS - ORC DTC/warning lamp","owner_letter_url":"/webselfservice/pdf/ca_en/Y79.pdf","type_of_campaign":"SAFETY","vin_live_date":"2021-11-19","vin_campaign_status":"Incomplete but repair parts are available","condition_and_risk":"The Occupant Restraint Control (ORC) module on your vehicle may have the incorrect software. The airbag warning indicator may not illuminate to notify the operator of possible compromised airbag system functionality. If specific ORC internal faults are active, then a diagnostic trouble code (DTC) will not be set and the airbag warning indicator may not illuminate. The internal faults will disable deployment of both the driver and passenger airbag squib (related to airbag venting post deployment) and knee airbags. Reduced occupant protection in the event of a crash may result in an increased risk of injury to motor vehicle occupants.","repair_description":"Your dealer will reprogram the ORC module with correct software. The estimated repair time is about a half hour.","agency_report_date":"2021-11-10","repair_date":"9999-01-01"}]}}]})`;
}
}
I probably should have been a little more clear on what Im attempting to do. Im building a google spreadsheet for my service dept. When they enter vehicles that need to be serviced to the spreadsheet I want the script to grab the vin from the spreadsheet and run the api call then return some of the values inside the response to the spreadsheet. I know currently my script has a variable set up for the vin but I figured I would add the code for pulling the vin from the spreadsheet after I could figure out how to even correctly parse the response to return certain values inside.
Currently the only way I know to parse then return specific values from a api call response is by code like this var foo = JSON.parse then accessing the it like (foo["Results"][0]["valueIwantToReturn"])
I know Im probably in over my head a little bit so I appreciate the help you are giving.
It is JSONP, not JSON. You could extract the 'JSON part' to parse it to json:
const content = 'showVinInfo({...})';
const json = JSON.parse(content.match(/^.+?\(({.*})\)$/)[1]);
const content = outputSample();
const json = JSON.parse(content.match(/^.+?\(({.*})\)$/)[1]);
console.log(json);
function outputSample() {
return `showVinInfo({"vin_recall":[{"vin_status":"success","campaign_status":"success","last_system_update_date":"2021-11-24","vehicle":{"vin":"1C4RJKBG4M8122507","niv":"","vehicle_desc":"JEEP GRAND CHEROKEE L LIMITED 4X4","model_year":"2021"},"recall_details":{"recall":[{"fca_campaign_number":"Y67","agency_campaign_number":"2021-576","campaign_desc":"2021 WL Radio Software Update","owner_letter_url":"/webselfservice/pdf/ca_en/Y67.pdf","type_of_campaign":"SAFETY","vin_live_date":"2021-09-23","vin_campaign_status":"REPAIRED","condition_and_risk":"Vehicles may fail to conform to Canada Motor Vehicle Safety Standard (CMVSS) 111 - Mirrors and Rear Visibility Systems. Suspect vehicles may not display the rear view image during a backing event. The vehicle operator will notice that the rearview image is not displayed if attempting to reference the image while backing. If this warning is not heeded, backing without verifying it is safe to do so could lead to an increased risk of injury to people outside the vehicle.","repair_description":"Your dealer will inspect and if necessary, update the radio software version","agency_report_date":"2021-09-21","repair_date":"2021-09-24"},{"fca_campaign_number":"Y79","agency_campaign_number":"2021-690","campaign_desc":"2021 WL & 2022 WS - ORC DTC/warning lamp","owner_letter_url":"/webselfservice/pdf/ca_en/Y79.pdf","type_of_campaign":"SAFETY","vin_live_date":"2021-11-19","vin_campaign_status":"Incomplete but repair parts are available","condition_and_risk":"The Occupant Restraint Control (ORC) module on your vehicle may have the incorrect software. The airbag warning indicator may not illuminate to notify the operator of possible compromised airbag system functionality. If specific ORC internal faults are active, then a diagnostic trouble code (DTC) will not be set and the airbag warning indicator may not illuminate. The internal faults will disable deployment of both the driver and passenger airbag squib (related to airbag venting post deployment) and knee airbags. Reduced occupant protection in the event of a crash may result in an increased risk of injury to motor vehicle occupants.","repair_description":"Your dealer will reprogram the ORC module with correct software. The estimated repair time is about a half hour.","agency_report_date":"2021-11-10","repair_date":"9999-01-01"}]}}]})`;
}

Updating the drake system states from robot hardware pose during initialization

I have been trying to set up a custom manipulation station with Kuka IIWA hardware in drake. I got the hardware interface working. When running a joint teleoperation code (adapted from drake/examples/manipulation_station/joint_teleop.py), the robot jerks violently (all joints tries to move to 0 position) at first and then continues to operate normally. On digging deeper, I found that this is caused by the FirstOrderLowPassFilter system. While advancing the simulation a tiny bit (simulator.AdvanceTo(1e-6)) to evaluate the LCM messages to set the initial GUI sliders-filter_initial_output_value-plant joint positions etc., to match the hardware, the FirstOrderLowPassFilter outputs a momentary value of 0. This sets the IIWA_COMMAND position to zero for an instance and causes a jerk.
How can I avoid this behavior?.
As a workaround, I am subscribing separately to the raw LCM message from the hardware, before initializing the drake systems and sets the filter_initial_output_value before advancing the simulation. Is this the recommended way?.
I think what you're doing (manually reading the LCM message) is fine.
In the alternative, look how a DiscreteDerivative offers the suppress_initial_transient = true option. Perhaps we could add a similar option (via unrestricted update event) to FirstOrderLowPassFilter so that the initial output value was sampled from the input at t == 0. But the event sequencing of startup may still be difficult. We essentially need to initialize the systems in their dataflow order, including refreshing output ports as events fire, which is not natively supported.
In another alternative, perhaps we could configure the IIWA_COMMAND publisher to not publish at t == 0, instead publishing only t >= 0.005.
FirstOrderLowPassFilter has a method to set the initial value. https://drake.mit.edu/doxygen_cxx/classdrake_1_1systems_1_1_first_order_low_pass_filter.html#aaef7539cfbf1acfa0cf487c371bc5360
It is used in the example that you copied from:
https://github.com/RobotLocomotion/drake/blob/master/examples/manipulation_station/joint_teleop.py#L146

How can I set the sampling rate in a Movesense device?

I can subscribe to the acceleration or angular velocity values with the movesense mobile libraries, but is there a way to change the sampling rate of the sensor?
The new movesense-device-lib (released today) has the new sensor API's that make it possible. The API's provide convenient and generic way to access all the "fast" sensors: Accelerometer, Gyroscope and Magnetic field. The paths have also been changed to make them less verbose (saves flash memory).
Here's a small intro on how the new API's work:
For each sensor there is a resource under root /Meas. /Meas/Acc, /Meas/Gyro and /Meas/Magn and they all work the same way.
Under the sensors root there is an Info resource that returns available sample rates as well as ranges. This is the result from GET'ing the /Meas/Acc/Info:
{
"SampleRates" : [13,26,52,104,208],
"Ranges" : [2,4,8,16]
}
Also under the sensors root there is a Config resource when one can GET & PUT the sensors global settings. At the moment the only setting in Accelerometer is GRange.
The data can be only SUBSCRIBED (no more GET in API), and the sample rate wanted is set as URL parameter: /Meas/Acc/{SampleRate} where the {SampleRate} is one of the values from the Info resource.
The sbuscribed data is returned in the object of the form: {timestamp, array of FloatVector3D's}. Different sample rates can return different number of measurements per notification in the array.
Word of caution: We have tested the accelerometer upto 208 Hz (as of today) so even if the API advertises higher rates, we have not yet tested how far we can push the sensor in practice.
Full Disclosure: I work for Movesense team

How can i tell if a peripheral is connected to GPIO?

I want to be able to detect when a peripheral sensor is NOT connected to my Raspberry Pi 3.
For example, if I have a GPIO passive infrared sensor.
I can get all the GPIO ports like this:
PeripheralManagerService manager = new PeripheralManagerService();
List<String> portList = manager.getGpioList();
if (portList.isEmpty()) {
Log.i(TAG, "No GPIO port available on this device.");
} else {
Log.i(TAG, "List of available ports: " + portList);
}
Then I can connect to a port like this:
try {
Gpio pir = new PeripheralManagerService().openGpio("BCM4")
} catch (IOException e) {
// not thrown in the case of an empty pin
}
However even if the pin is empty I can still connect to it (which technically makes sense, as gpio is just binary on or off). There doesn't seem to be any api, and I can't legitimately think of logically how you can differentiate between a pin that has a peripheral sensor connected and one that is "empty".
Therefore at the moment, there is no way for me to assert programmatically that my sensors and circuit is setup correctly.
Any one have any ideas? Is it even possible from a electronics point of view?
Reference docs:
https://developer.android.com/things/sdk/pio/gpio.html
There are lots of ways to do "presence detection" electrically, but nothing that you will find intrinsically in the SoC. You wouldn’t normally ask a GPIO pin if something is attached—it would have no way to tell you that.
Extra GPIO pins are often used to detect if a peripheral is attached to a connector. The plug for some sensor could include a “detect” line that is shorted to ground and pulls the GPIO low when the sensor is attached, for example. USB and SDIO do something similar with some dedicated circuitry in the interface.
You could also build more elaborate detection circuits using things like current sensing, but they would inevitably have to put out a binary signal that you capture through a dedicated GPIO.
This is easier to achieve for serial peripherals, since you can usually send a basic command and verify that you get a response.
Detection using solely the input line can be tough. First, you'd want to narrow the scope of the problem. Treat as not-present the condition of a sensor not being connected, the sensor being connected but not responding, or the sensor responding in an uncharacteristic manner.
So, if it is a digital sensor, then communicating with the sensor may be enough to tell if it is present or not (especially if checksums or parity bits are involved).
Some analog sensors also have specific specs on how it behaves when triggered. You can utilize deviation from those specs to determine if the sensor is not present.
If you have a digital sensor w/o any error checking on it's output, where you clock out data (so all 0s or all 1s is valid) or it's just a binary 1 or 0 for output, then you'd need external help. Same for most analog sensors.
This external help would be something where you put the system in a known controlled state, press a button, and it then checks the sensors for output within a specific range. To be absolutely sure, you'd want at least two different states, to ensure your digital or analog inputs didn't happen to be stuck at the correct state for your test.
Just about any other method would be external to the system. Using additional IO to "detect" a sensor could help increase confidence the sensor is there, but you could get false positives where all you've learned is that "something" is there - not necessarily the sensor you expect.

Contiki OS CC2538: Reducing current / power consumption

I am trying to drive down the current consumption of the contiki os running on the CC2538 development kit.
I would like to operate the device from a CR2032 with a run life of 2 years. To achieve this I would need an average current less than 100uA.
However when I run the following at 3V, I get the following results:
contiki/examples/hello-world = 0.4mA - 2mA
contiki/examples/er-rest-example/er-example-client = 27mA
contiki/examples/er-rest-example/er-example-server = 27mA
thingsquare websocket example = 4mA
I have also designed my own target platform based on the cc2538 and get similar results.
I have read the guide at https://github.com/contiki-os/contiki/blob/648d3576a081b84edd33da05a3a973e209835723/platform/cc2538dk/README.md
and have ensured that in the contiki-conf.h file:
- LPM_CONF_ENABLE 1
- LPM_CONF_MAX_PM 2
Can anyone give me some pointers as to how I can get the current down. It would be most appreciated.
Regards,
Shane
How did you measure the current?
You have to be aware that using a basic ampere meter to measure the current consumption of contiki-os wouldn't give you relevant results. The system is turning on/off the radio at a relative high rate (8Hz by default) in order to perform the CCA. This might not be very easy to catch for an ampere meter.
To have an idea of the current consumption when the device is in deep sleep (and then make calculation to determine the averaged current consumption), I'd rather put the device in the PM state before the program reach the infinite while loop. I used the following code to do that:
lpm_enter();
REG(SYS_CTRL_PMCTL) = SYS_CTRL_PMCTL_PM2;
do { asm("wfi"::); } while(0);
leds_on(LEDS_RED); // should not reach here
while(1){
...
On the CC2538, the CCA check consumes about 10-15mA and last approximately 2ms. When the radio transmit a packet, it consume 25mA. Have a look at this post: Contiki UDP packet transmission duration with CC2538.
Furthermore, to save a little more current, turn off the serial com:
#define CC2538_CONF_QUIET 1
Are you using the SmartRF board? If you want to make proper current measurement with this board, you have to remove every jumpers: P486, P487, P411 and P408. Keep only the jumpers of BTN_SEL and the RESET signals.

Resources