How to send multiple characteristics under one BLE Service stm32wb15 - embedded

I try to read 2 characteristics ( accelerometer and distance laser sensor )under one BLE Service. I can read distance data successfully but other AccelValueZ data is always zero.SensorHeightValue is int16_t type. How to read this two data from my phone ? Code is :
void MPU6050_Receive_Sensor_Data(void){
double xAccel ,yAccel ,zAccel;
mpu6050_get_measurement(&xAccel, &yAccel, &zAccel);
P2P_Server_App_Context.SensorControl.MPU6050AccelValueX = xAccel;
P2P_Server_App_Context.SensorControl.MPU6050AccelValueY = yAccel;
P2P_Server_App_Context.SensorControl.MPU6050AccelValueZ = zAccel;
P2PS_STM_App_Update_Char(P2P_READ1_CHAR_UUID, (uint8_t *)&P2P_Server_App_Context.SensorControl.MPU6050AccelValueZ);
if((P2P_Server_App_Context.SensorControl.MPU6050AccelValueZ <= 100) && (P2P_Server_App_Context.SensorControl.MPU6050AccelValueZ >= -100)){
VL53L1X_Receive_Sensor_Data_Action();
}
return;
}
void VL53L1X_Receive_Sensor_Data(void){
P2P_Server_App_Context.SensorControl.SensorHeightValue = vl53l1x_get_measurement();
P2PS_STM_App_Update_Char(P2P_READ_CHAR_UUID, (uint8_t *)&P2P_Server_App_Context.SensorControl.SensorHeightValue);
// P2PS_STM_App_Update_Char(P2P_READ1_CHAR_UUID, (uint8_t *)&P2P_Server_App_Context.SensorControl.MPU6050AccelValueZ);
return;
}```

Related

STM32 Crash on Flash Sector Erase

I'm trying to write 4 uint32's of data into the flash memory of my STM32F767ZI so I've looked at some examples and in the reference manual but still I cannot do it. My goal is to write 4 uint32's into the flash and read them back and compare with the original data, and light different leds depending on the success of the comparison.
My code is as follows:
void flash_write(uint32_t offset, uint32_t *data, uint32_t size) {
FLASH_EraseInitTypeDef EraseInitStruct = {0};
uint32_t SectorError = 0;
HAL_FLASH_Unlock();
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.Sector = FLASH_SECTOR_11;
EraseInitStruct.NbSectors = 1;
//EraseInitStruct.Banks = FLASH_BANK_1; // or FLASH_BANK_2 or FLASH_BANK_BOTH
st = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
if (st == HAL_OK) {
for (int i = 0; i < size; i += 4) {
st = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_USER_START_ADDR + offset + i, *(data + i)); //This is what's giving me trouble
if (st != HAL_OK) {
// handle the error
break;
}
}
}else {
// handle the error
}
HAL_FLASH_Lock();
}
void flash_read(uint32_t offset, uint32_t *data, uint32_t size) {
for (int i = 0; i < size; i += 4) {
*(data + i) = *(__IO uint32_t*)(FLASH_USER_START_ADDR + offset + i);
}
}
int main(void) {
uint32_t data[] = {'a', 'b', 'c', 'd'};
uint32_t read_data[] = {0, 0, 0, 0};
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
flash_write(0, data, sizeof(data));
flash_read(0, read_data, sizeof(read_data));
if (compareArrays(data,read_data,4))
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7,SET);
}
else
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14,SET);
}
return 0;
}
The problem is that before writing data I must erase a sector, and when I do it with the HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError), function, the program always crashes, and sometimes even corrupts my codespace forcing me to update firmware.
I've selected the sector farthest from the code space but still it crashes when i try to erase it.
I've read in the reference manual that
Any attempt to read the Flash memory while it is being written or erased, causes the bus to
stall. Read operations are processed correctly once the program operation has completed.
This means that code or data fetches cannot be performed while a write/erase operation is
ongoing.
which I believe means the code should ideally be run from RAM while we operate on the flash, but I've seen other people online not have this issue so I'm wondering if that's the only problem I have. With that in mind I wanted to confirm if this is my only issue, or if I'm doing something wrong?
In your loop, you are adding multiples of 4 to i, but then you are adding i to data. When you add to a pointer it is automatically multiplied by the size of the pointed type, so you are adding multiples of 16 bytes and reading past the end of your input buffer.
Also, make sure you initialize all members of EraseInitStruct. Uncomment that line and set the correct value!

STM32F4 - USART - Receive data array - reads only first frame

today I'm fighting with controlling my uC from the PC.
On a button click, I'm sending data to uC which is to change some values in the program. First of all, the problem is that my program reads only first frame received. Secondly, my program gets stuck when I reinitialize PDM_Filter Structure
What is important - Rx buffer of USART is 16-bit.
Data format is like 6x byte (uint8) that are:
0) ASCII symbol - ! or # or & - symbol indicates what happens next;
1) mic_gain; 2)3) HP Filter cutoff freq; 4)5) LP Filter cutoff freq
So I am receiving 3 x uint16
How it looks like on uC code:
union
{
uint16_t szes[3];
uint8_t os[6];
}RxBuffer;
Interrupt Handler - I had cut the part that works just fine.
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
j=0;
while (j<3)
{
RxBuffer.szes[j] = USART_ReceiveData(USART1);
j++;
}
if(RxBuffer.os[0] == 39)
{
DoFlag = false;
I2S_Cmd(SPI2, DISABLE);
//_PDM(sampling_frequency, RxBuffer.szes[2], RxBuffer.szes[1]);
Filter.HP_HZ = RxBuffer.szes[1];
Filter.LP_HZ = RxBuffer.szes[2];
PDM_Filter_Init(&Filter);
GPIO_SetBits(GPIOD, LED_Blue);
mic_gain = RxBuffer.os[1];
Delay(1000);
GPIO_ResetBits(GPIOD, LED_Blue);
I2S_Cmd(SPI2, ENABLE);
DoFlag = true;
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
How intialization of PDM_Filter structure (from libPDMFilter_Keil.lib) looks for me:
Filter.Fs = frequency_s;
Filter.HP_HZ = high_pass_cutoff;
Filter.LP_HZ = low_pass_cutoff;
Filter.In_MicChannels = 1;
Filter.Out_MicChannels = 1;
PDM_Filter_Init(&Filter);
I'm trying to change cutoff frequencies - in order to do so, I reinitialize structure.

RFduino not pulling NMEA strings from GPS

I'm having trouble using the TinyGPS library to parse Lat and Lon. Is this library compatible with the RFduino? I can read NMEA strings by loading a blank sketch to the RFduino and then just opening the Serial Monitor, so I know that the GPS data is going through the serial port, but when I try to get the Lat or Lon into a variable, it fills the variable with 999999999. I'm sending this data through BLE to an android. If I don't try to get GPS data, I can send any value I want in the lat or lon variables and it appears in my custom Android App. I read somewhere that the softserial library doesn't work on rfduino. Is this true? If not, I would be able to print my data through the hard serial port, making troubleshooting much easier. Below I've attached the code I'm using on my RFduino. Any advice would be appreciated.
// CODE //
#include <RFduinoBLE.h>
#include <TinyGPS.h>
TinyGPS gps;
long lat = 5; //Load lat/lon with junk value for testing
long lon = 6;
char latBuf[20];
char lonBuf[20];
void setup() {
// this is the data we want to appear in the advertisement
// (if the deviceName and advertisementData are too long to fix into the 31 byte
// ble advertisement packet, then the advertisementData is truncated first down to
// a single byte, then it will truncate the deviceName)
RFduinoBLE.advertisementData = "ledbtn";
// start the BLE stack
RFduinoBLE.begin();
Serial.begin(9600);//For GPS Communication
}
void loop(){
char c = byte(Serial.read());
gps.encode(c);
gps.get_position(&lat,&lon); // get latitude and longitude
// send position as char[]
String latString = String(lat);
String lonString = String(lon);
latString.toCharArray(latBuf, 20);
lonString.toCharArray(lonBuf, 20);
RFduinoBLE.send(lonBuf, 20);
}
void RFduinoBLE_onDisconnect()
{
}
void RFduinoBLE_onReceive(char *data, int len)
{
RFduinoBLE.send(lonBuf, 20);
}
One problem I see: the loop() is trying to read out the GPS coordinates every time loop is executed. This approach has two problems: 1) the loop doesn't wait until serial data is ready, and 2) the loop doesn't wait until the received GPS data is valid.
From reading http://arduino.cc/en/Tutorial/ReadASCIIString and http://arduiniana.org/libraries/tinygps/ I recommend rewriting loop() to something like this:
loop() {
char c;
float fLat, fLon;
unsigned long fix_age;
static unsigned long previous_fix_age = 0;
// If nothing to read; do nothing.
// Read as many characters as are available.
while (Serial.available() > 0) {
// Tell the GPS library about the new character.
c = Serial.read();
gps.encode(c);
gps.f_get_position(&flat, &flon, &fix_age);
if (fix_age != TinyGPS::GPS_INVALID_AGE && fix_age != previous_fix_age) {
// new GPS data is valid, new, and ready to be printed
previous_fix_age = fix_age; // remember that we've reported this data.
String latString = String(lat);
...the rest of the code you already have to print the lat and lon.
}
}
}
The code about previous_fix_age is there so that the loop prints coordinates only when a new fix has been received from the GPS.

Embedded: SDHC SPI write issue

I am currently working at a logger that uses a MSP430F2618 MCU and SanDisk 4GB SDHC Card.
Card initialization works as expected, I also can read MBR and FAT table.
The problem is that I can't write any data on it. I have checked if it is write protected by notch, but it's not. Windows 7 OS has no problem reading/writing to it.
Though, I have used a tool called "HxD" and I've tried to alter some sectors (under Windows). When I try to save the content to SD card, the tool pop up a windows telling me "Access denied!".
Then I came back to my code for writing to SD card:
uint8_t SdWriteBlock(uchar_t *blockData, const uint32_t address)
{
uint8_t result = OP_ERROR;
uint16_t count;
uchar_t dataResp;
uint8_t idx;
for (idx = RWTIMEOUT; idx > 0; idx--)
{
CS_LOW();
SdCommand(CMD24, address, 0xFF);
dataResp = SdResponse();
if (dataResp == 0x00)
{
break;
}
else
{
CS_HIGH();
SdWrite(0xFF);
}
}
if (0x00 == dataResp)
{
//send command success, now send data starting with DATA TOKEN = 0xFE
SdWrite(0xFE);
//send 512 bytes of data
for (count = 0; count < 512; count++)
{
SdWrite(*blockData++);
}
//now send tow CRC bytes ,through it is not used in the spi mode
//but it is still needed in transfer format
SdWrite(0xFF);
SdWrite(0xFF);
//now read in the DATA RESPONSE TOKEN
do
{
SdWrite(0xFF);
dataResp = SdRead();
}
while (dataResp == 0x00);
//following the DATA RESPONSE TOKEN are a number of BUSY bytes
//a zero byte indicates the SD/MMC is busy programing,
//a non_zero byte indicates SD/MMC is not busy
dataResp = dataResp & 0x0F;
if (0x05 == dataResp)
{
idx = RWTIMEOUT;
do
{
SdWrite(0xFF);
dataResp = SdRead();
if (0x0 == dataResp)
{
result = OP_OK;
break;
}
idx--;
}
while (idx != 0);
CS_HIGH();
SdWrite(0xFF);
}
else
{
CS_HIGH();
SdWrite(0xFF);
}
}
return result;
}
The problem seems to be when I am waiting for card status:
do
{
SdWrite(0xFF);
dataResp = SdRead();
}
while (dataResp == 0x00);
Here I am waiting for a response of type "X5"(hex value) where X is undefined.
But most of the cases the response is 0x00 (hex value) and I don't get out of the loop. Few cases are when the response is 0xFF (hex value).
I can't figure out what is the problem.
Can anyone help me? Thanks!
4GB SDHC
We need to see much more of your code. Many µC SPI codebases only support SD cards <= 2 GB, so using a smaller card might work.
You might check it yourself: SDHC needs a CMD 8 and an ACMD 41 after the CMD 0 (GO_IDLE_STATE) command, otherwise you cannot read or write data to it.
Thank you for your answers, but I solved my problem. It was a problem of timing. I had to put a delay at specific points.

libusb-1.0 - Where does the data go after a successful libusb_bulk_transfer() call?

I ran the following code sample obtained from a tutorial here: http://www.dreamincode.net/forums/topic/148707-introduction-to-using-libusb-10/
I ran it against a tablet running Android 4 attached via USB to a MacBook Pro running Mac OS X Mountain Lion.
The output contained "Writing Successful!" so I assume libusb_bulk_transfer() worked correctly. My question is where did the 4 bytes of data got transferred to? Can I save it to a file on the Android tablet?
Thanks for your help!
#include <iostream>
#include <libusb.h>
using namespace std;
int main() {
libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
libusb_device_handle *dev_handle; //a device handle
libusb_context *ctx = NULL; //a libusb session
int r; //for return values
ssize_t cnt; //holding number of devices in list
r = libusb_init(&ctx); //initialize the library for the session we just declared
if(r < 0) {
cout<<"Init Error "<<r<<endl; //there was an error
return 1;
}
libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation
cnt = libusb_get_device_list(ctx, &devs); //get the list of devices
if(cnt < 0) {
cout<<"Get Device Error"<<endl; //there was an error
return 1;
}
cout<<cnt<<" Devices in list."<<endl;
dev_handle = libusb_open_device_with_vid_pid(ctx, 5118, 7424); //these are vendorID and productID I found for my usb device
if(dev_handle == NULL)
cout<<"Cannot open device"<<endl;
else
cout<<"Device Opened"<<endl;
libusb_free_device_list(devs, 1); //free the list, unref the devices in it
unsigned char *data = new unsigned char[4]; //data to write
data[0]='a';data[1]='b';data[2]='c';data[3]='d'; //some dummy values
int actual; //used to find out how many bytes were written
if(libusb_kernel_driver_active(dev_handle, 0) == 1) { //find out if kernel driver is attached
cout<<"Kernel Driver Active"<<endl;
if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it
cout<<"Kernel Driver Detached!"<<endl;
}
r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of device (mine had jsut 1)
if(r < 0) {
cout<<"Cannot Claim Interface"<<endl;
return 1;
}
cout<<"Claimed Interface"<<endl;
cout<<"Data->"<<data<<"<-"<<endl; //just to see the data we want to write : abcd
cout<<"Writing Data..."<<endl;
r = libusb_bulk_transfer(dev_handle, (2 | LIBUSB_ENDPOINT_OUT), data, 4, &actual, 0); //my device's out endpoint was 2, found with trial- the device had 2 endpoints: 2 and 129
if(r == 0 && actual == 4) //we wrote the 4 bytes successfully
cout<<"Writing Successful!"<<endl;
else
cout<<"Write Error"<<endl;
r = libusb_release_interface(dev_handle, 0); //release the claimed interface
if(r!=0) {
cout<<"Cannot Release Interface"<<endl;
return 1;
}
cout<<"Released Interface"<<endl;
libusb_close(dev_handle); //close the device we opened
libusb_exit(ctx); //needs to be called to end the
delete[] data; //delete the allocated memory for data
return 0;
}
The libusb_bulk_transfer() function writes the data at the specified endpoint. Its an address, access it, print it, or you can copy it, do some case conversion and dump it to an outgoing endpoint. And, then perform a read through libusb_bulk_transfer()