nRF52 DK BLE can't sleep - bluetooth

I’m using Nordic nRF52 DK in order to make a BLE application that broadcasts data through a custom characteristic with Read and Notify properties.
I’m currently working with PlatformIO and Visual Studio Code for this project.
To measure the power consumption I am using the Power Profiler kit.
The power consumption is always above 2.3mA which is extremely high based on Online Power Profiler For Ble.
Online Power Profiler For Ble settings:
{
"chip": "1",
"voltage": "3",
"dcdc": "on",
"lf_clock": "lfrc",
"radio_tx": "-40",
"ble_type": "adv",
"ble_int": "1000",
"tx_size": "20"
}
My goal is to put the board to sleep until a new Bluetooth connection is established and then execute the eventQueue for the sensor value update and other processes. After the disconnection event the board must be put to sleep again.
First, I tried to implement sleep for an mbed sample project with BLE features BLE_BatteryLevel.
Note: I removed the blink event from the sample code.
I have added _event_queue,break_dispatch() inside onDisconnectionComplete callback function, in order to force the ble to exit from its functions.
I do not know if it is the right choice but I wanted somehow to exit ble’s event queue and let the board sleep.
I have tried the following:
Use a DeepSleepLock object in a block of code in order to execute sleep on its destruction
Using ThisThread::sleep(5s)
int main()
{
while (true)
{
ThisThread::sleep_for('5s');
{
DeepSleepLock dp;
BLE &ble = BLE::Instance();
ble.onEventsToProcess(schedule_ble_events);
BatteryDemo demo(ble, event_queue);
demo.start();
ThisThread::sleep_for('5s');
}
}
}
Using void sleep()
int main()
{
BLE &ble = BLE::Instance();
ble.onEventsToProcess(schedule_ble_events);
BatteryDemo demo(ble, event_queue);
demo.start();
ble.shutdown();
sleep();
}
Power Profiler Screenshot from BLE onDisconection
Hal_sleep functions
int main()
{
BLE &ble = BLE::Instance();
ble.onEventsToProcess(schedule_ble_events);
BatteryDemo demo(ble, event_queue);
demo.start();
ble.shutdown();
hal_sleep();
}
Disable input and output using at the start of main
mbed_file_handle(STDIN_FILENO)->enable_input(false);
mbed_file_handle(STDIN_FILENO)->enable_output(false);
Adding rtos::Kernel::attach_idle_hook(&sleep); at the start of main()
int main()
{
rtos::Kernel::attach_idle_hook(&sleep);
BLE &ble = BLE::Instance();
ble.onEventsToProcess(schedule_ble_events);
BatteryDemo demo(ble, event_queue);
demo.start();
}
Nothing seems to put the board on sleep, the power consumption is always high.
Power Profiler Screenshots
BLE Enabled State
BLE Disconnected state (sleep)
I couldn't find any example for power consumption and sleep using BLE.

Related

How to "simulate" processing time consuming tasks for FreeRTOS aimed to discuss real-time system topics using Linux simulator

I'm trying to use FreeRTOS to discuss real time concepts with students, using the POSIX-Linux simulator framework. To accomplish this, I have to find a way of wasting processing time in a controlled way (simulating task in "Running" status by a predetermined period of processing time).
Delays are not good because they change the task status to "Block" and, with a preemptive scheduler, it means the scheduler can give the processor to other tasks. Using Linux native time control approaches (e.g. using clock_gettime() to build the logic) are not good because I don't have the control of the exact running time of a single task, specially with preemptiveness. Regular iterations (for, while) don't have the control I need for processing time (my computer and students computers will have different processing times depending on their architectures).
During my researches on FreeRTOS documentation, I found both the TaskStatus_t struct and the vTaskGetInfo() function which were supposed to help me out. And my problem is when I implement something like:
// Creating the task
if (xTaskCreate(
app_task,
task1_info.name,
configMINIMAL_STACK_SIZE,
(void *) &task1_info,
task1_info.priority,
NULL
) != pdPASS) printf("Task create error %s\n", task1_info.name);
// ...
starting_time_ticks = xTaskGetTickCount(); // starting time in ticks
vTaskStartScheduler();
// ...
static void app_task( void *pvParameters )
// The task itself
{ // ...
for( ;; )
{ // ...
app_proc_ticks(
pdMS_TO_TICKS( task_info.proc_time_ms ),
task_info.name
); // consuming processing time...
// ... }
// ... }
static void app_proc_ticks( TickType_t proc_time_ticks, uint8_t name[APP_MAX_MSG_SIZE])
// Consuming the number of ticks in order to attain a certain processing time
{
TaskHandle_t xHandle;
TaskStatus_t xTaskDetails;
xHandle = xTaskGetHandle( name );
configASSERT( xHandle );
vTaskGetInfo( xHandle, &xTaskDetails, pdTRUE, eInvalid );
TickType_t begin = xTaskDetails.ulRunTimeCounter;
while((xTaskDetails.ulRunTimeCounter - begin) < proc_time_ticks)
{
vTaskGetInfo( xHandle, &xTaskDetails, pdTRUE, eInvalid );
}
}
For a task_info.proc_time_ms equal to 25 ms, my code shows up as the task is consuming around 250 ms worth of ticks, a error factor of 10x. The way I count this is with the following "timestamp" strategy:
static TickType_t get_timestamp_ticks() {
return xTaskGetTickCount() - starting_time_ticks;
}
As far as I can see, I'm having problems to understand and properly convert xTaskDetails.ulRunTimeCounter time unit (ticks, ms, or probably something else). Also probably some tick to ms constant I'm not aware of. Right now, to convert from "ms" to "ticks" I'm using pdMS_TO_TICKS() macro and to convert from "ticks" to "ms" I'm multiplying the number of ticks by portTICK_RATE_MS.
Also, after make, I'm using taskset -c 0 ./build/posix_demo to run and ensure the use of a single processor by my executable.
I'm not trying to hold on to this solution, though. If anyone could share how to do a time controlled delay with "real consumption of processing time" for tasks in FreeRTOS, I would appreciate it as well.

Bluetooth LE Scan filter MAC address often not working for all the list

My app scans for bluetooth devices. I would like filtering the scan by a list of MAC address. With Samsung S7 Android 8.0 that works always well.
But I have problem with others devices as Xiaomi Android 8 and Honor Android 7.
When I start the scan, often I haven't possibility to get all Bluetooth devices MAC listed in the filter.
Stop/Start scan : Sometimes I get only the one MAC adress.
Stop/Start scan : Then I get all.
Stop/Start scan : Then I get only the one and the third...
Please where is the problem?
I would like get an error when I call startscan if the writing filter has fail.
Or is it possible to flush or reset the filter?
BluetoothManager manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
mBluetoothLeScanner = manager.getAdapter().getBluetoothLeScanner();
ArrayList<ScanFilter> filters = new ArrayList<ScanFilter>();
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
String[] filterlist = {
"AA:AA:AA:AA:AA:AA",
"BB:BB:BB:BB:BB:BB",
"CC:CC:CC:CC:CC:CC",
};
for (int i=0; i< filterlist.length ; i++) {
ScanFilter filter = new ScanFilter.Builder().setDeviceAddress(filterlist[i]).build();
filters.add(filter);
Log.v("Filter: "," "+ filters.get(i).getDeviceAddress());
}
Log.d(TAG, "filters" + filters );
mBluetoothLeScanner.startScan(filters, settings, mLeScanCallback);

Can step counter be used for api level less than 19 in android?

I've been trying to build a step counter for my own use. I tried this code,
Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
if (countSensor !=null
{
sensorManager.registerListener(this,CountSensor,SensorManager.SENSOR_DELAY_UI);
} else {
Toast.makeText(this,"Count Sensor not Availabe in this device !!",Toast.LENGTH_LONG).show();
}
but, I did not get a positive output. It says that I have lower API than 19. How can I get things working for lower APIs?

Ambient Light Sensor Interrupt Status register not getting updated

I'm using WinCE 7 Visual Studio 2008 and writing a driver code for ALS (MAX44009). I have written the following code for reading the interrupt status register and displaying messages when the interrupt has occurs. But, it works randomly for a few times only. For eg., when I close the sensor with my hand, I get the messages only few times, and then, it doesn't go into the data==1 condition even when it has to interrupt and continues to loop. The threshold timer is 0. The AlsRegRead function does an I2CRead. pAlsDrvInfo is the driver context. ADD_ALS_INT_STATUS is 0. DumpAlsRegistry function will print the content of all the registers except register 0x0.
while(1)
{
AlsRegRead(pAlsDrvInfo, ADD_ALS_INT_STATUS, &data, sizeof(UINT8));
if (data == 1)
{
DumpAlsRegistry(pAlsDrvInfo);
RETAILMSG(1,(L"Interrupt Received...\r\n"));
}
}
Please guide me where I'm making mistake.
I have found the reason behind this. Two issues had been behind this and both of them are equally important.
1) The sensor had been in a partially damaged state.
2) It requires some delay. So, I added Sleep(1000) at the start of the loop.
while(1)
{
Sleep(1000);
AlsRegRead(pAlsDrvInfo, ADD_ALS_INT_STATUS, &data, sizeof(UINT8));
if (data == 1)
{
DumpAlsRegistry(pAlsDrvInfo);
RETAILMSG(1,(L"Interrupt Received...\r\n"));
}
}
Thanks.

JSR 256 battery events

How can I detect whenever the power cord is unplugged from electrical socket using JSR 256?
You would add javax.microedition.io.Connector.sensor to the API Permissions tab of the Application Descriptor of the project properties.
From a quick look at the specifications of the JSR:
(you might want to look for code examples, starting with Appendix D of the spec itself, the latest JavaME SDK, Sony Ericsson developer website, then google)
As always, I would be worried about fragmentation in the diverse implementations of the JSR, but here's my first idea:
import javax.microedition.sensor.*;
SensorInfo[] powerSensorInfoArray = SensorManager.findSensors("power","ambient");
//let's assume there is one SensorInfo in the array.
//open a connection to the sensor.
SensorConnection connection = (SensorConnection)Connector.open(powerSensorInfoArray[0].getUrl(), Connector.READ);
// add a DataListener to the connection
connection.setDataListener(new MyDataListener(), 1);
// implement the data listener
public class MyDataListener implements DataListener {
public void dataReceived(SensorConnection aSensor, Data[] aDataArray, boolean isDataLost) {
//let's assume there is only one channel for the sensor and no data was lost.
// figure out what kind of data the channel provides.
int dataType = aDataArray[0].getChannelInfo().getDataType();
//now, I suggest you switch on dataType and print the value on the screen
// experimentation on the JSR256 implementation you're targetting seems to be
// the only way to figure out out power data is formatted and what values mean.
//only one of the following 3 lines will work:
double[] valueArray = aDataArray[0].getDoubleValues();
int[] valueArray = aDataArray[0].getIntValues();
Object[] valueArray = aDataArray[0].getObjectValues();
// let's assume one value in the valueArray
String valueToPrint = "" + valueArray[0];
// see what happens with that and you plug or unplug the power supply cable.
}
}
You'll need to add javax.microedition.io.Connector.sensor to your MIDlet permissions.
-------EDIT------
Documentation from the JSR-256 implementation on Sony-Ericsson Satio phone (S60 5th edition):
The battery charge sensor has the following characteristics:
Quantity: battery_charge
Context type: device
URL: sensor:battery_charge;contextType=device;model=SonyEricsson
Channels: (index: name, range, unit)
0: battery_charge, 0-100, percent
1: charger_state, 0-1, boolean

Resources