Project aims to use LED panel controlled through UART with an nucleo STM32 board with shields BLE IDB05A1 & MEMS IKS01A1
Dependencies: mbed X_NUCLEO_IKS01A2 X_NUCLEO_IDB0XA1 BLE_API
main.cpp
- Committer:
- waby38
- Date:
- 2017-11-24
- Revision:
- 3:60fe58ad8c7d
- Parent:
- 2:74b8978081c5
File content as of revision 3:60fe58ad8c7d:
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "XNucleoIKS01A2.h"
#include "ble/BLE.h"
#include "ble/services/UARTService.h"
#include "Serial.h"
/* Instantiate the mems expansion board */
static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(D14, D15, D4, D5);
/* Retrieve the composing elements of the expansion board */
static LSM303AGRMagSensor *magnetometer = mems_expansion_board->magnetometer;
static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
static LPS22HBSensor *press_temp = mems_expansion_board->pt_sensor;
static LSM6DSLSensor *acc_gyro = mems_expansion_board->acc_gyro;
static LSM303AGRAccSensor *accelerometer = mems_expansion_board->accelerometer;
/* BLE part */
#define UART_BUFFER (UARTService::BLE_UART_SERVICE_MAX_DATA_LEN*10)
const static char DEVICE_NAME[] = "$PANEL$";
UARTService *uartServicePtr;
static char BLEBuffRX[UART_BUFFER];
static uint8_t BLEBuffPos=0;
void onBleError(ble_error_t error);
/* pc uart part */
static char uartBuff[UART_BUFFER];
static uint8_t uartBuffPos=0;
Serial uart1(USBTX,USBRX);
#define DEBUG uart1.printf
/* Led panel part */
#define PANEL_PAGE_NUMBER 26
#define PANEL_PAGE_SIZE 256
Serial uart_panel(PA_9,PA_10);
static uint8_t panel_disppage=0;
static char panel_msg[PANEL_PAGE_NUMBER][PANEL_PAGE_SIZE]={
"<FE><MA><WC><FE>Bienvenue a STMicroeletronics",
"<FE><MA><WC><FE>Welcome to STMicroeletronics",
"<FE><MA><WC><FE>Today is <KD>",
"<FE><MA><WC><FE>It is <KT>",
"<FE><MA><WC><FE>Temp is <TEMPERAT>",
"<FE><MA><WC><FE>I am a <CE>STM32L476",
"<FE><MA><WC><FE>with <CE>MEMs <CB>and <CE>BLE <CB>shields"
};
typedef enum {
SCROLL_DEFAULT,
SCROLL_LEFT,
SCROLL_RIGHT,
SCROLL_UP,
SCROLL_DOWN
} panel_effect_e ;
panel_effect_e panel_effect = SCROLL_DEFAULT;
DigitalOut led1(LED1);
Ticker ticker;
/* Helper function for printing floats & doubles */
static char *printDouble(char* str, double v, int decimalDigits=2)
{
int i = 1;
int intPart, fractPart;
int len;
char *ptr;
/* prepare decimal digits multiplicator */
for (;decimalDigits!=0; i*=10, decimalDigits--);
/* calculate integer & fractinal parts */
intPart = (int)v;
fractPart = (int)((v-(double)(int)v)*i);
/* fill in integer part */
sprintf(str, "%i.", intPart);
/* prepare fill in of fractional part */
len = strlen(str);
ptr = &str[len];
/* fill in leading fractional zeros */
for (i/=10;i>1; i/=10, ptr++) {
if(fractPart >= i) break;
*ptr = '0';
}
/* fill in (rest of) fractional part */
sprintf(ptr, "%i", fractPart);
return str;
}
void panel_sendmsg(char line, char page, char* text){
char buff[PANEL_PAGE_SIZE];
char* pos_t;
char* pos_p;
char* pos_h;
char* pos_e;
char* panel_reset;
uint8_t i, checksum=0;
pos_t=strstr(text,"<SC>");
if(pos_t!=0) {
sprintf(buff,"<ID00>%s",text);
for(i=6; i<strlen(buff); i++){
checksum ^= buff[i];
}
sprintf(buff,"%s%02X<E>", buff, checksum);
uart1.printf("panel msg = %s\r\n", buff);
uart_panel.printf(buff);
return;
}
sprintf(buff, "<ID00><L%c><P%c>%s", line, page, text);
pos_t=strstr(buff,"<TEMPERAT>");
if(pos_t!=0) {
float sensor_temp;
char temp[3];
hum_temp->get_temperature(&sensor_temp);
sprintf(temp, "%02d", (int)sensor_temp);
buff[pos_t-buff]=' '; /* replace < */
buff[pos_t-buff+1]=temp[0]; /* replace T */
buff[pos_t-buff+2]=temp[1]; /* replace E */
buff[pos_t-buff+3]='<'; /* replace M */
buff[pos_t-buff+4]='U'; /* replace P */
buff[pos_t-buff+5]='3'; /* replace E */
buff[pos_t-buff+6]='A'; /* replace R */
buff[pos_t-buff+7]='>'; /* replace A */
buff[pos_t-buff+8]='C'; /* replace T */
buff[pos_t-buff+9]=' '; /* replace > */
}
pos_p=strstr(buff,"<PRESSI>");
if(pos_p!=0) {
float sensor_pres;
char pres[3];
press_temp->get_pressure(&sensor_pres);
sprintf(pres, "%02d", (int)sensor_pres);
buff[pos_p-buff]=' '; /* replace < */
buff[pos_p-buff+1]=pres[0]; /* replace P */
buff[pos_p-buff+2]=pres[1]; /* replace R */
buff[pos_p-buff+3]='m'; /* replace E */
buff[pos_p-buff+4]='B'; /* replace S */
buff[pos_p-buff+5]='a'; /* replace S */
buff[pos_p-buff+6]='r'; /* replace I */
buff[pos_p-buff+7]=' '; /* replace > */
}
pos_h=strstr(buff,"<HUM>");
if(pos_h!=0) {
float sensor_hum;
char hum[3];
hum_temp->get_humidity(&sensor_hum);
sprintf(hum, "%02d", (int)sensor_hum);
buff[pos_h-buff]=' '; /* replace < */
buff[pos_h-buff+1]=hum[0]; /* replace H */
buff[pos_h-buff+2]=hum[1]; /* replace U */
buff[pos_h-buff+3]='\''; /* replace M */
buff[pos_h-buff+4]=' '; /* replace > */
}
switch(panel_effect) {
case SCROLL_RIGHT:
pos_e=strstr(buff,"<F");
buff[pos_e-buff+2]='F';
buff[pos_e-buff+14]='F';
break;
case SCROLL_LEFT:
pos_e=strstr(buff,"<F");
buff[pos_e-buff+2]='E';
buff[pos_e-buff+14]='E';
break;
case SCROLL_UP:
pos_e=strstr(buff,"<F");
buff[pos_e-buff+2]='I';
buff[pos_e-buff+14]='I';
break;
case SCROLL_DOWN:
pos_e=strstr(buff,"<F");
buff[pos_e-buff+2]='J';
buff[pos_e-buff+14]='J';
break;
case SCROLL_DEFAULT:
/* No change */
break;
}
panel_reset=strstr(buff,"<RES>");
if(panel_reset!=0){
sprintf(buff,"<ID00><D*>");
}
for(i=6; i<strlen(buff); i++){
checksum ^= buff[i];
}
sprintf(buff,"%s%02X<E>", buff, checksum);
uart1.printf("panel msg = %s pos_d@ %d\r\n", buff, pos_h-buff);
uart_panel.printf(buff);
wait(0.1);
checksum=0;
if(panel_disppage < page-'A'+1){
panel_disppage = page-'A'+1;
sprintf(buff, "<ID00><TA>00010100009912302359");
for(i=0; i<panel_disppage; i++){
sprintf(buff,"%s%c",buff,i+'A');
}
for(i=6; i<strlen(buff); i++){
checksum ^= buff[i];
}
sprintf(buff,"%s%02X<E>", buff, checksum);
uart1.printf("panel msg = %s\r\n", buff);
uart_panel.printf(buff);
}
}
void periodicCallback(void){
int32_t axes[3];
panel_effect_e new_panel_effect;
acc_gyro->get_x_axes(axes);
new_panel_effect = SCROLL_DEFAULT;
accelerometer->enable();
acc_gyro->enable_x();
// DEBUG("accelerometer : %d %d %d\r\n", axes[0], axes[1], axes[2]);
if(axes[1]<-800){ /* move up */
new_panel_effect = SCROLL_UP;
}
if(axes[1]>800){ /* move down */
new_panel_effect = SCROLL_DOWN;
}
if(axes[0]<-800){ /* move to left */
new_panel_effect = SCROLL_LEFT;
}
if(axes[0]>800){ /* move to right */
new_panel_effect = SCROLL_RIGHT;
}
if(new_panel_effect != panel_effect){
uint8_t i=0;
panel_effect=new_panel_effect;
/* while(strlen(panel_msg[i])){
panel_sendmsg('1','A'+i,panel_msg[i]);
i++;
} */
while(i<26){
if(strlen(panel_msg[i])){
panel_sendmsg('1','A'+i,panel_msg[i]);
}
i++;
}
}
}
/* UART */
void uartRx(void)
{
if(uart1.readable()){
uartBuff[uartBuffPos] = uart1.getc();
if((uartBuff[uartBuffPos] == '\r') || (uartBuff[uartBuffPos] == '\n') || (uartBuffPos >= UART_BUFFER)) {
uartBuff[uartBuffPos] = '\0';
/* We are sending the whole string even if less than BLE_UART_SERVICE_MAX_DATA_LEN otherwise we need to wait */
uartServicePtr->write(uartBuff, (uartBuffPos/UARTService::BLE_UART_SERVICE_MAX_DATA_LEN +1) * UARTService::BLE_UART_SERVICE_MAX_DATA_LEN);
DEBUG("TX : %s\r\n", uartBuff);
if(uartBuff[0]!='0'){
strcpy(panel_msg[uartBuff[1]-'A'],&uartBuff[2]);
}
panel_sendmsg(uartBuff[0],uartBuff[1], &uartBuff[2]);
memset(uartBuff, 0, UART_BUFFER);
uartBuffPos = 0;
}
else
uartBuffPos++;
}
}
/* BLE */
void BleConnectionCallback(const Gap::ConnectionCallbackParams_t *params) {
DEBUG("BLE Client Connected!\n\r");
DEBUG("Please type a string and press return\r\n");
led1 = 1;
}
void BleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
(void)params;
DEBUG("BLE Client Disconnected!\r\n");
BLE::Instance().gap().startAdvertising(); // restart advertising
led1= 0;
}
void BleOnDataWrittenCallback(const GattWriteCallbackParams *params) {
if (params->handle == uartServicePtr->getTXCharacteristicHandle()){
DEBUG("RX: %s\r\n", (char *)params->data);
strncpy(&BLEBuffRX[BLEBuffPos], (char *)params->data, params->len);
BLEBuffPos+=params->len;
if((params->len==UARTService::BLE_UART_SERVICE_MAX_DATA_LEN) && (BLEBuffRX[BLEBuffPos-1]!='\n')){
return;
}
BLEBuffRX[BLEBuffPos-1]='\0';
DEBUG("TX=>Panel: L%c P%c =>%s<=\r\n", BLEBuffRX[0],BLEBuffRX[1], &BLEBuffRX[2]);
DEBUG("pos dans le pannel %x PANEL_PAGE_NUMBER%d\n\r",BLEBuffRX[1]-'A',PANEL_PAGE_NUMBER);
if(BLEBuffRX[0]!='0'){
int dippage=BLEBuffRX[1]-'A';
DEBUG("disppage: %x BLEBUFFRX=%d\n\r",dippage,BLEBuffRX[1]);
strcpy(panel_msg[BLEBuffRX[1]-'A'],&BLEBuffRX[2]);
DEBUG("panel_MGS: %s \n\r",panel_msg[26]);
}
panel_sendmsg(BLEBuffRX[0],BLEBuffRX[1], &BLEBuffRX[2]);
uart1.printf("%c\n",panel_msg);
BLEBuffPos=0;
}
}
void onBleError(ble_error_t error) {
DEBUG("BLE Error: %d\r\n");
/* Handle error now */
}
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
BLE& ble = params->ble;
ble_error_t error = params->error;
if (error != BLE_ERROR_NONE) {
/* In case of error, forward the error handling to onBleInitError */
onBleError(error);
return;
}
/* Ensure that it is the default instance of BLE */
if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
return;
}
ble.gap().onConnection(BleConnectionCallback);
ble.gap().onDisconnection(BleDisconnectionCallback);
ble.gattServer().onDataWritten(BleOnDataWrittenCallback);
DEBUG("BLE UARTService: ");
/* Setup primary service. */
UARTService uartService(ble);
uartServicePtr = &uartService;
DEBUG("Started\r\n");
/* setup advertising */
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
//ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
ble.gap().setAdvertisingInterval(500); /* 500ms. */
ble.gap().startAdvertising();
while (true) {
ble.waitForEvent();
}
}
int main(void)
{
uint8_t i=0;
led1=0;
hum_temp->enable();
press_temp->enable();
uart_panel.baud(9600);
uart1.baud(115200);
uart1.attach(uartRx,Serial::RxIrq);
/* Init panel */
while(strlen(panel_msg[i])){
panel_sendmsg('1','A'+i,panel_msg[i]);
i++;
}
ticker.attach(periodicCallback, 2);
BLE &ble = BLE::Instance();
ble.init(bleInitComplete);
}