Skip navigation
gsgill112

BLOG 15 : BLE Subsystem

Posted by gsgill112 Nov 13, 2017

Hey guys, Let dive into the BLE Sub Section. I was not able to implement much on this front but it is not very difficult to implement. Let me go through the basics first

 

What is BLE ??

BLE Stands for Bluetooth Low Energy. It is a Simple yet Powerful Technology specially designed for Low power Applications. It's Strength lies in the STATE information transmission.

 

So, You may ask STATE information ?? Well that means something like Is the Device ON or OFF, is the fan ON or OFF what is the value of the PWM Signal going to LED, etc. State is just a small piece of information not something like IMAGES or AUDIO/ VIDEO, etc.

 

That being Cleared, BLE being Point to Point Communication protocol is organised  into 2 Main Roles Client / Server OR Peripheral / Central  OR Slave / Master

These means out of two devices one will me Master and one Will be Salve. The Master will control the Slave (Ohh This sounds more like 50 Shades of Grey !!! Shit. !!)

These 2 profiles Majorly are known as GAP or Generic Access Profiles for you guys with BigAss Specks

(Thanks to LadyAda for this Image)

 

Moving on, the devices we usually implement as a End user device is a BLE Peripheral / Slave / Client device. So everything now on will be based on this statement.

So, In a Client Device How To send data to other Devices ?

Well, to ease things up Bluetooth implements a Service / Attribute Structure.

Puzzeled ??

 

Don't Worry, Let Me Explain.

 

Lets say you want to order a Brand New iPhone X/TEN/10/ Whatever !!!! Online I would prefer flipkart/ Amazon

So you would like to go to a Website that would Sell you the Item ?? like Amazon or best buy !! this is our Seller Service 

Now Once you land up  at Amazon You would like to go to the Mobile Section who offer Mobile Sale Services !! This is the Characteristic or Attributes

Now We would like to  Go to the iPhone Section which would contain information on all iPhones !! This is the values in the Characteristic or Attributes 

All of the Above is Geeky Known as GATT or Generic Attribute Profile

 

Refer this diagram for ease of understanding

 

Finally the Values which we will play with are in Name Value pair, i.e. UUID, VALUE.

 

This was the Super super dooper short introduction on BLE If you are interested in more I suggest gat a Pink hair Die and meet LadyAda Here.

 

Moving to the implementation Again ST was good to provide a LIBRARY for BLE HERE with an Example Application HERE .

While this is good for understanding the Basics of How things work. It's not enough to implement a custom BLE Service.  For that I have these two links Below

1.     BLE Link for bed BLE API

2.     How to change BLE_GAP Profile Selection

3.     How to create custom GATT Services

 

Now there are some Predefined GATT Profiles Provided by Bluetooth themselves found at this link.

 

Finally , Let me show the little work I have done in BLE Part !! Its Actually nothing Great

 

Adding the Headers including GATT Profiles

#include "ble/BLE.h"
#include "LEDService.h"
#include "BatteryService.h"
#include "DeviceInformationService.h"

 

Setting the parameters like Device List LIST

const static char     DEVICE_NAME[] = "IoToWSbSr";
static const uint16_t uuid16_list[] = {LEDService::LED_SERVICE_UUID,
                                       //GattService::UUID_BATTERY_SERVICE,
                                       GattService::UUID_DEVICE_INFORMATION_SERVICE};


LEDService *ledServicePtr;

 

Setting the GATT Parameters

 /* Setup Device Identification service. */
    DeviceInformationService devInfoService(ble, "ST Micro", "NUCLEO-L476RG", "XXXX", "v1.0", "v1.0", "v1.0");
  

 

You can extend the to anything you would like to.

 

As I have Not yet customised the BLE Part much This is pretty much the basics. It will be easy to implement the custom GATT profiles .

 

Thanks for Reading

Regards,

GS Gill

Ok, In this Blog I will talk about implementation of the Sensor Subsystem in My project.

 

Firstly the Role of Sensor Subsystem was to identify the weather for ride and to send it to the User. I had Dropped the Idea of pothole detection as it was not a worth Idea, moreover In my Nextion display You could just touch to report the pothole. see the BUMP Button below !!

 

As there was a mBed Library available online HERE as well as an Example Program available HERE it was easy to get started with the Library and implement the rest.

 

Now I would like to post my Implementation code snippet

 

Some Important defn

const static float seaLevelPressure = 1013.25;
const static float declinationAngle = 0.003839724;
float alt, LPS22HB_p, LPS22HB_p_previous, LPS22HB_t, HTS221_h, HTS221_t;
float angle;
int32_t LSM303AGR_a[3],LSM303AGR_m[3];
int32_t LSM6DSL_a[3],LSM6DSL_g[3];

 

Message Banks to be displayed on the Nextion display

// Message Bank  
// To 
/*      Var                     Bank            Msg 
 *      greatingMessages        1               0-2
 *      pressureMessages        2               0-1
 *      ridingMessages          3               0-2
 *      weatherMessages         4               0-5
*/ 
  
const char* greatingMessages[3] = {
    "Good Morning",
    "Good Evening",
    "Good Day"
};
const char* pressureMessages[2] = {
    "Up Up Up the hill we go",
    "Down we goooooo.... Yeeaahhh....."
};
const char* ridingMessages[3] = {
    "Com'on its a Pleasent Fine AWESOME day :)",
    "Hey Its a Holiday ! I will pickup dirt :(",
    "I know you are sleeping :| "
};
const char* weatherMessages[6] = {
    "Its pleasent to ride bike :)",
    "Its not to bad :) a bit Humid :)",
    "Its HUMID !! :|",
    "Not Today, Its very Humid :\\",
    "Its Chilling :O",
    "Its Hot :<"
};

 

Obj Creation

/* Instantiate the 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;

 

Function called to update Messages based on Sensor Values

void updateMessage(void){
    hum_temp->get_temperature(&HTS221_t);
    hum_temp->get_humidity(&HTS221_h);
    // printf("HTS221: [temp] %7s C,   [hum] %s%%\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
   
    // Use this in another function  
    if(HTS221_h < 70){
        messageInUse=0;
    }else if(HTS221_h > 70 && HTS221_h < 80){
        messageInUse=1;
    }else if(HTS221_h > 80 && HTS221_h < 90){
        messageInUse=2;
    }
    else{
        messageInUse=3;
    }
    if(HTS221_t < 20){
        messageInUse=4;
    }else if(HTS221_t > 20 && HTS221_t < 35){
        messageInUse=0;
    }else{
        messageInUse=5;
    }
    
    press_temp->get_temperature(&LPS22HB_t);
    press_temp->get_pressure(&LPS22HB_p);
    //printf("LPS22HB: [temp] %7s C, [press] %s mbar\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
    if(LPS22HB_p_previous > LPS22HB_p){
        messageInUse=0;
    }else{
        messageInUse=1;
    }
    if(LPS22HB_t < 20){
        messageInUse=4;
    }else if(LPS22HB_t > 20 && LPS22HB_t < 35){
        messageInUse=0;
    }else{
        messageInUse=5;
    }
    
    //#ifdef DEBUG
        nextion.printf("%s\n",weatherMessages[messageInUse]);
    //#endif
}

 

inside Perodic Function to gather sensor data periodically

#ifdef DEBUG
        nextion.printf("Speedy Calc Over ---- \n Sensor Data Polling Begin\n");
    #endif    
    
    hum_temp->get_temperature(&HTS221_t);
    hum_temp->get_humidity(&HTS221_h);
    
    #ifdef DEBUG
    printf("HTS221: [temp] %7s C,   [hum] %s%%\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
    #endif
    
    press_temp->get_temperature(&LPS22HB_t);
    press_temp->get_pressure(&LPS22HB_p_previous);
    //wait(5);
    
    #ifdef DEBUG
    printf("LPS22HB: [temp] %7s C, [press] %s mbar\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
    printf("---\r\n");
    #endif
    
    magnetometer->get_m_axes(LSM303AGR_m);
    
    #ifdef DEBUG
    printf("LSM303AGR [mag/mgauss]:  %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
    #endif
    
    accelerometer->get_x_axes(LSM303AGR_a);
    
    #ifdef DEBUG
    printf("LSM303AGR [acc/mg]:  %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
    #endif
    
    acc_gyro->get_x_axes(LSM6DSL_a);
    
    #ifdef DEBUG
    printf("LSM6DSL [acc/mg]:      %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
    #endif
    
    acc_gyro->get_g_axes(LSM6DSL_g);
    
    #ifdef DEBUG
    printf("LSM6DSL [gyro/mdps]:   %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
    #endif
    
    //Altitude computation based on http://keisan.casio.com/exec/system/1224585971 formula 
    alt = pow((double)(seaLevelPressure/LPS22HB_p),(double)(1/5.257)) - 1;
    alt = alt * (LPS22HB_t + 273.15);
    alt = alt / 0.0065;
    
    angle -= declinationAngle;
    // Correct for when signs are reversed.
    if(angle < 0){   
      angle += 2*M_PI;
    }
    // Check for wrap due to addition of declination.
    if(angle > 2*M_PI){
      angle -= 2*M_PI;
    }
    
    angle = angle * 180/M_PI;
    
    updateMessage();

 

Hope you found this SHORT UPDATE useful

 

If you want more information please comment and I will include it in the blog  

 

Thanks for Reading

Regards,

GS Gill

During the testing of the assembly which held fine I met with a Accident on my cycle Damn those Disk Breaks .

I have got More, but I am avoiding uploading due to the content of the images

 

As humiliating it would sound Nothing much happened to the stm32 but the Nextion Display got damages and I myself got a bit damaged

 

As I mentioned that I have limited time for Project. As of Now its 20 OCT 2017 and I have to move to a remote location. I won't be able to take the Kit with me but will post all the blogs and work later if I get internet there It was fun working on the project and the challenges faced during the implementation.

 

The still Not Implemented part of the project is the BLE Subsection which has a progress of 80%. BLE is working as normal and battery profile as well as Device Information profiles are implemented. Only remaining part in BLE is the Custom profile needed for sending data like which greeting message string has to be used, and Sensor Values to and fro.

 

As soon as I reach back home in DEC I will continue the project and will post the final Result Hope the judges understand and rate me accordingly .

 

Here is a look at the final code implementation of my main.c

/*
 ******************************************************************************
 * @file    main.cpp
 * @author  GS Gill
 * @version V1.0.0
 * @date    14-SEP-2017
@brief Smart Bike Smart Rider Source for  NUCLEO-L476RG using 
 *          MEMS Inertial & Environmental Sensor Nucleo expansion board and
 *          BLE Expantion Board.
 ******************************************************************************
 *
 Smart Bike Smart Rider Source for  NUCLEO-L476RG 
 * Please refer <> for further information and build instructions.
 *
 * Requires [SHIELD]
 *    +-- Nucleo IDB0XA1 BLE Shield
 *    +-- Nucleo IKS01A2 Motion Sensing Shield
 *
 * Requires [External]
 *    +-- Nextion 3.2" Enhanced Diaplsy
 *    +-- Hall Effect Sensors
 *    +-- Battery Module with Solar Charging
 *
 * 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 "ble/BLE.h"
#include "LEDService.h"
#include "BatteryService.h"
#include "DeviceInformationService.h"
#include "XNucleoIKS01A2.h"


#define M_PI   3.14
#define cycleTyreRadius 0.2
//#define oneRevolutionDist 2*M_PI*cycleTyreRadius


//#define DEBUG 1                   //Enable Debug Statements 




// PIN Maps 
DigitalOut actuatedLED(LED1, 0);
DigitalOut errorLed(LED1, 0);            // error indicator 


InterruptIn mybutton(USER_BUTTON);           // TESTING STATEMENT    test
InterruptIn hallSensor(PA_12);               // Using st Morpho Connectors as all arduino pins are used by shields.


DigitalIn  dispBoot(PC_4);            // Connected to D4 :: Display Boot Sucessful  
DigitalIn  mPnP(PB_1);            // Connected to D10 :: Music PLay n Pause
DigitalIn  mRt(PB_2);            // Connected to D11 :: Music Rt
DigitalIn  rideS(PB_11);            // Connected to D5 :: Ride Screen
DigitalIn  bumpP(PB_12);            // Connected to D6 :: Bump Pressed
DigitalIn  scS(PB_13);            // Connected to D7 :: Self Check Screen
DigitalIn  musicS(PB_14);            // Connected to D8 :: Music Screen 
DigitalIn  mLt(PB_15);            // Connected to D9 :: Music Left






// Objects 
//Serial nextion(PC_4, PC_5);        // Sending Data to Nextion Display
Serial nextion(SERIAL_TX, SERIAL_RX);


Timer tick;


//Static Variables
static const char* ver="SbSr_V00";
static const char terminator = 0xFF;       // Nextion termination sequence
char* dispSpeed = "n0.val=";                              // Nextion RIDE screen commands
char* dispAvg = "n2.val=";
char* dispDist = "n1.val=";
char* accl_check = "t1.txt=\"Acc ";                                    // Nextion Self Check screen
char* hx_check = "t2.txt=\"Hx ";
char* temp_check = "t3.txt=\"Temp ";
char* gyro_check = "t4.txt=\"Gyro ";
char* bx_check = "t5.txt=\"Bk ";
char* ble_check = "t6.txt=\"BLE ";
char* wifi_check = "t7.txt=\"WiFi ";
char* pass = "PASS\"";
char* fail = "FAIL\"";


const static float seaLevelPressure = 1013.25;
const static float declinationAngle = 0.003839724;
float alt, LPS22HB_p, LPS22HB_p_previous, LPS22HB_t, HTS221_h, HTS221_t;
float angle;
int32_t LSM303AGR_a[3],LSM303AGR_m[3];
int32_t LSM6DSL_a[3],LSM6DSL_g[3];


// for Debug of sensors 
  uint8_t id;
  float value1, value2;
  char buffer1[32], buffer2[32];
  int32_t axes[3];
  
// Message Bank  
// To 
/*      Var                     Bank            Msg 
 *      greatingMessages        1               0-2
 *      pressureMessages        2               0-1
 *      ridingMessages          3               0-2
 *      weatherMessages         4               0-5
*/ 
  
const char* greatingMessages[3] = {
    "Good Morning",
    "Good Evening",
    "Good Day"
};
const char* pressureMessages[2] = {
    "Up Up Up the hill we go",
    "Down we goooooo.... Yeeaahhh....."
};
const char* ridingMessages[3] = {
    "Com'on its a Pleasent Fine AWESOME day :)",
    "Hey Its a Holiday ! I will pickup dirt :(",
    "I know you are sleeping :| "
};
const char* weatherMessages[6] = {
    "Its pleasent to ride bike :)",
    "Its not to bad :) a bit Humid :)",
    "Its HUMID !! :|",
    "Not Today, Its very Humid :\\",
    "Its Chilling :O",
    "Its Hot :<"
};


/* Instantiate the 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;


//Variables
static volatile bool  triggerSensorPolling = false;            // one sec delay for BL sensor Data
char nextionScreen = '0';                                      // Nextion Screen indicator
char nextionMusic = '0';                                       // Nextion Music controls indicator
bool nextionBoot = false;                                      // Nextion Sucessful Boot indicator
float totalDist, dist, ridingSpeed, avgSpeed[5], avgSpeedF;
uint8_t avgCtr, hallSensorCounter, timeP, timeN, timex, stopC;
char* dispMsg = "";
uint8_t messageInUse, BLEStat;


const static char     DEVICE_NAME[] = "IoToWSbSr";
static const uint16_t uuid16_list[] = {LEDService::LED_SERVICE_UUID,
                                       //GattService::UUID_BATTERY_SERVICE,
                                       GattService::UUID_DEVICE_INFORMATION_SERVICE};


LEDService *ledServicePtr;


void pressed(void)              // TESTING STATEMENT    test
{
    nextion.printf("Test Sucessful\n");
}


void irqcallback_hallSensor(void)
{
#ifdef DEBUG
    nextion.printf("In Hall Callback\n");
#endif
    errorLed = !errorLed;
    //hallSensor.disable_irq();
    stopC = 0;                        // enables calculation of Speed
    timex = tick.read_ms();
    hallSensorCounter++;
    tick.reset();
    //hallSensor.enable_irq();


}


/* Helper function for printing floats & doubles */
static char *print_double(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 updateMessage(void){
    hum_temp->get_temperature(&HTS221_t);
    hum_temp->get_humidity(&HTS221_h);
    // printf("HTS221: [temp] %7s C,   [hum] %s%%\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
   
    // Use this in another function  
    if(HTS221_h < 70){
        messageInUse=0;
    }else if(HTS221_h > 70 && HTS221_h < 80){
        messageInUse=1;
    }else if(HTS221_h > 80 && HTS221_h < 90){
        messageInUse=2;
    }
    else{
        messageInUse=3;
    }
    if(HTS221_t < 20){
        messageInUse=4;
    }else if(HTS221_t > 20 && HTS221_t < 35){
        messageInUse=0;
    }else{
        messageInUse=5;
    }
    
    press_temp->get_temperature(&LPS22HB_t);
    press_temp->get_pressure(&LPS22HB_p);
    //printf("LPS22HB: [temp] %7s C, [press] %s mbar\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
    if(LPS22HB_p_previous > LPS22HB_p){
        messageInUse=0;
    }else{
        messageInUse=1;
    }
    if(LPS22HB_t < 20){
        messageInUse=4;
    }else if(LPS22HB_t > 20 && LPS22HB_t < 35){
        messageInUse=0;
    }else{
        messageInUse=5;
    }
    
    //#ifdef DEBUG
        nextion.printf("%s\n",weatherMessages[messageInUse]);
    //#endif
}


void perodic(void)
{
#ifdef DEBUG
    nextion.printf("In perodic\n Start Speed Calc\n");
#endif


    if (tick.read_ms() > 10000) { //(tick.read_ms() < 100 || tick.read_ms() > 10000 )       // check if bike is ideal standing ..
        stopC = 1;
        //tick.reset();
    } else  stopC = 0;


    if (stopC == 0) {
        timex = timex * 100 * 60; //min
        ridingSpeed = (2 * M_PI * cycleTyreRadius) / timex ;   //  in mtr/sec
    } else if(stopC == 1) {
        ridingSpeed = 0;


    }
    
    #ifdef DEBUG
        nextion.printf("Riding Speed = %f\n",ridingSpeed);
    #endif
        
    totalDist = 2* M_PI * cycleTyreRadius * hallSensorCounter;     // calculating total distance


    #ifdef DEBUG
        nextion.printf("Total Distance  = %f\n",totalDist);
    #endif
    
    avgSpeed[avgCtr] = ridingSpeed;
    avgCtr++;
    if(avgCtr == 4) avgCtr = 0;


    for(int i = 0; i == 4; i++) {    // calculation of avg speed
        avgSpeedF += avgSpeed[i];
    }
    avgSpeedF = avgSpeedF/5;
    
    #ifdef DEBUG
        nextion.printf("Average Speed  = %f\n",avgSpeedF);
    #endif


    triggerSensorPolling = true;
    
    #ifdef DEBUG
        nextion.printf("Speedy Calc Over ---- \n Sensor Data Polling Begin\n");
    #endif    
    
    hum_temp->get_temperature(&HTS221_t);
    hum_temp->get_humidity(&HTS221_h);
    
    #ifdef DEBUG
    printf("HTS221: [temp] %7s C,   [hum] %s%%\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
    #endif
    
    press_temp->get_temperature(&LPS22HB_t);
    press_temp->get_pressure(&LPS22HB_p_previous);
    //wait(5);
    
    #ifdef DEBUG
    printf("LPS22HB: [temp] %7s C, [press] %s mbar\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
    printf("---\r\n");
    #endif
    
    magnetometer->get_m_axes(LSM303AGR_m);
    
    #ifdef DEBUG
    printf("LSM303AGR [mag/mgauss]:  %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
    #endif
    
    accelerometer->get_x_axes(LSM303AGR_a);
    
    #ifdef DEBUG
    printf("LSM303AGR [acc/mg]:  %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
    #endif
    
    acc_gyro->get_x_axes(LSM6DSL_a);
    
    #ifdef DEBUG
    printf("LSM6DSL [acc/mg]:      %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
    #endif
    
    acc_gyro->get_g_axes(LSM6DSL_g);
    
    #ifdef DEBUG
    printf("LSM6DSL [gyro/mdps]:   %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
    #endif
    
    //Altitude computation based on http://keisan.casio.com/exec/system/1224585971 formula 
    alt = pow((double)(seaLevelPressure/LPS22HB_p),(double)(1/5.257)) - 1;
    alt = alt * (LPS22HB_t + 273.15);
    alt = alt / 0.0065;
    
    angle -= declinationAngle;
    // Correct for when signs are reversed.
    if(angle < 0){   
      angle += 2*M_PI;
    }
    // Check for wrap due to addition of declination.
    if(angle > 2*M_PI){
      angle -= 2*M_PI;
    }
    
    angle = angle * 180/M_PI;
    
    updateMessage();
    
    // Screen and Controlls Checks
    if(dispBoot){
        nextionBoot = true;
        nextionScreen ='B';
    }else if(rideS){
        nextionScreen ='R';
    }else if(bumpP){
        nextionScreen ='B';
    }else if(musicS){
        nextionScreen ='M';
    }else if(scS){
        nextionScreen ='S';
    }
    
    if(mPnP){
        nextionMusic ='P';
    }else if(mLt){
        nextionMusic ='L';
    }else if(mRt){
        nextionMusic ='R';
    }
    
    //Update the Display Screen
    if(nextionScreen =='R') {             // checking if nextio display is on rise screen
        nextion.printf(dispSpeed);                                   // updating Speed Value on Nextion Display
        nextion.printf("%d",(int)(ridingSpeed));
        nextion.printf("%c%c%c",terminator,terminator,terminator);
        
        nextion.printf(dispAvg);                                   // updating Avg Speed Value on Nextion Display
        nextion.printf("%d",(int)(avgSpeedF));
        nextion.printf("%c%c%c",terminator,terminator,terminator);
        
        nextion.printf(dispDist);                                   // updating Distance Value on Nextion Display
        nextion.printf("%d",(int)(totalDist));
        nextion.printf("%c%c%c",terminator,terminator,terminator);
    }else if(nextionScreen =='S' && scS){
        if(hum_temp->read_id(&id)){
            nextion.printf(hx_check);
            nextion.printf(pass);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
        }else {
            nextion.printf(hx_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
            nextion.printf(temp_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
        }
        if(press_temp->read_id(&id)){
            nextion.printf(bx_check);
            nextion.printf(pass);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
        }else{
            nextion.printf(bx_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
        }
        if(magnetometer->read_id(&id)){
            nextion.printf(temp_check);
            nextion.printf(pass);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
        }else {
            nextion.printf(temp_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
        }
        if(accelerometer->read_id(&id)){
            nextion.printf(accl_check);
            nextion.printf(pass);
            nextion.printf("%c%c%c",terminator,terminator,terminator);   
        }else {
            nextion.printf(accl_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);   
        }
        if(acc_gyro->read_id(&id)){
            nextion.printf(gyro_check);
            nextion.printf(pass);
            nextion.printf("%c%c%c",terminator,terminator,terminator);   
        }else{
            nextion.printf(gyro_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);  
        }
        if(BLEStat){
            nextion.printf(ble_check);
            nextion.printf(pass);
            nextion.printf("%c%c%c",terminator,terminator,terminator);   
        }else{
            nextion.printf(ble_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);  
        }
    while(scS);
    }
    
    #ifdef DEBUG
        nextion.printf("sensor Collection Over \n perodic over\n");
    #endif
}


void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    (void)params;
    BLE::Instance().gap().startAdvertising(); // restart advertising
}


/**
 * This callback allows the LEDService to receive updates to the ledState Characteristic.
 *
 * @param[in] params
 *     Information about the characterisitc being updated.
 */
void onDataWrittenCallback(const GattWriteCallbackParams *params) {
    if ((params->handle == ledServicePtr->getValueHandle()) && (params->len == 1)) {
        actuatedLED = *(params->data);
    }
}


/** 
 * This function is called when the ble initialization process has failled 
 */ 
void onBleInitError(BLE &ble, ble_error_t error) 
{ 
    /* Initialization error handling should go here */ 
    BLEStat = 1;
} 


/** 
 * Callback triggered when the ble initialization process has finished 
 */ 
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 */
        onBleInitError(ble, error);
        return;
    }


    /* Ensure that it is the default instance of BLE */
    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }


    ble.gap().onDisconnection(disconnectionCallback);
    ble.gattServer().onDataWritten(onDataWrittenCallback);


    /* Setup Device Identification service. */
    DeviceInformationService devInfoService(ble, "ST Micro", "NUCLEO-L476RG", "XXXX", "v1.0", "v1.0", "v1.0");
    
    bool initialValueForLEDCharacteristic = true;
    ledServicePtr = new LEDService(ble, initialValueForLEDCharacteristic);


    /* setup advertising */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.gap().setAdvertisingInterval(1000); /* 1000ms. */
    ble.gap().startAdvertising();


    while (true) {
        ble.waitForEvent();
    }
}


int main(void)
{
    stopC = 1;                         // skips calculation of speed if set to : 1
    BLEStat = 0;
    hallSensorCounter = 0;
    nextion.baud(9600);                //Setting Up nextion Display  see the Issues.txt for more info
    errorLed = 1;      //To confirm System has Started :: Loading Screen on the Display
    wait(0.5);
    errorLed = 0;
#ifdef DEBUG
    nextion.printf("Welcome To SbSr Version %s\n",ver); // Serial Print only Debug MODE as serial is shared with Nextion Display
#endif
    wait(0.1);
    
    /* Enable all sensors */
    hum_temp->enable();
    press_temp->enable();
    magnetometer->enable();
    accelerometer->enable();
    acc_gyro->enable_x();
    acc_gyro->enable_g();
    
    mybutton.fall(&pressed);                          // TESTING STATEMENT    test
    hallSensor.fall(&irqcallback_hallSensor);
    
    Ticker ticToc;
    ticToc.attach(perodic, 0.2f); // blink LED every second
    
    BLE &ble = BLE::Instance();
    ble.init(bleInitComplete);
}



































































































 

Its about 600 Lines of Code which is nicely documented for everyone to understand. Thanks for going through my blogs.

 

I conclude my official submission for SbSr project HERE. I will update TWO more Blog on BLE and Sensor Subsystem and ONE complimentary Blog on introduction to ARM mBed platform.  I would like to thank the Judges, Readers for going through my content any feedback would be appreciated. I would also like to thank Element14 and ST for giving me a chance to project and pitch my IDEA and to participate in an full on manner

 

I am also regretful of the fact the due to time constraints I was not able to complete the project, But I have definitely put up the best I could have done .

 

Once again thanks and see you guys in another Design challenge .

 

Just to RECAP

Click here to view all my videos on IoTonWheels Design Challenge.

https://www.youtube.com/playlist?list=PLnp4Q6KlcA9lsg305T_LPAd7MFnrqGo5f

 

 

Thanks and Regards,

GS GILL

Hey guys Lets now decide how to plus this Cable mess on my Bike

 

I am a poor Man without any support of a 3D Printer or something fancy, But I am a huge fan of Recycled or Found objects

So in a nearby Glass shop I found a piece of broken Acrylic Sheet laying around and the guy was ok if I took It so I took it happily

After marking the holders for STM32 on the acrylic I stripped the acrylic to the required dimensions and marked the board mounting holes. (I am not sure why STM stuck with 3 screws at least 4 are required )

Further making some more holes for cable ties The mounting assembly was ready   

As I have already mentioned the Acrylic flexes because there is only one screw at bottom of board, but that is not an issue as little flexing is good for us  

unfortunately it was 4 in the morning and I forgot to click images of the board assembly mounted on the cycle

 

Thanks for reading

Regards,

GS Gill

PREVIOUS PAGE                                                                           NEXT PAGE

Hey Guys, This is another quick update on the Nextion Interface Setup and I will also demonstrate it in the video below.

As I have Blogged in my previous blogs that the RX Interrupt on Nextion display was not working and I had planned for a Parallel bus handshake between STM32 and Arduino Nano while leaving the Rx decoding part with Arduino Nano.

 

The primary reason of the Rx Interrupt failure was lack of Buffered Serial Library implementation for STM32L476R Nucleo. After couple of failed attempts of implementation myself I had to fall back on the previously mentioned method.

 

So, The way to approach was to Decode the incoming messages from the Nextion Display in Arduino and convert the data into Parallel bus oaf Arduino which we can further poll in Perodic Routine of STM32.

 

 

Arduino Code - For Converting the Nextion messages to Parallel bus For Arduino NANO

NOTE : I am using Official Nextion Libraries

 

Nextion messages look something like This

0X65 0X00 0X02 0X01 0XFF 0XFF 0XFF

and details on each subsection can be found on the Nextion Instruction Set Page


#include 
#include "Timer.h"
#include 


SoftwareSerial nextion(2, 3);// Nextion TX to pin 2 and RX to pin 3 of Arduino


Nextion myNextion(nextion, 9600); //create a Nextion object named myNextion using the nextion serial port @ 9600bps
Timer t;


void setup() {
  Serial.begin(9600);
  myNextion.init();
  pinMode(4,OUTPUT);     // Display Boot Successful
  digitalWrite(4,LOW);
  pinMode(5,OUTPUT);     // Ride Screen     
  digitalWrite(5,LOW);
  pinMode(6,OUTPUT);     // Bump Pressed
  digitalWrite(6,LOW);
  pinMode(7,OUTPUT);     // Self Check Screen
  digitalWrite(7,LOW);
  pinMode(8,OUTPUT);     // Music Screen
  digitalWrite(8,LOW);
  pinMode(9,OUTPUT);     // Music Left
  digitalWrite(9,LOW);
  pinMode(10,OUTPUT);     // Music Play Pause
  digitalWrite(10,LOW);
  pinMode(11,OUTPUT);     // Music Right 
  digitalWrite(11,LOW);
  t.every(1000, resetAll);
}


void loop() {
  String message = myNextion.listen(); //check for message
  if(message != ""){ // if a message is received...


   if( message == "6"){
    Serial.println("Booted");
    digitalWrite(6,HIGH);
   }else if (message == '0xFF'){
     Serial.println("Off");
     digitalWrite(4,LOW);
    // Ride Screen  
    digitalWrite(5,LOW);
    // Options Screen
    digitalWrite(6,LOW);
    // Self Check Screen
    digitalWrite(7,LOW);
    // Music Screen
    digitalWrite(8,LOW);
    // Music Left
    digitalWrite(9,LOW);
    // Music Play Pause
    digitalWrite(10,LOW);
    // Music Right 
    digitalWrite(11,LOW);
   }else if (message == "7"){
     Serial.println("Riding Screen");
     digitalWrite(5,HIGH);
   }else if (message == "65 7 6 0 ffff ffff ffff"){
     Serial.println("Bump Pressed");
     digitalWrite(6,HIGH);
   }else if (message == "8"){
     Serial.println("Music Controls");
     digitalWrite(8,HIGH);
   }else if (message == "65 8 4 0 ffff ffff ffff"){
     Serial.println("Left Button");
     digitalWrite(9,HIGH);
   }else if (message == "65 8 5 0 ffff ffff ffff"){
     Serial.println("Play Pause Button");
     digitalWrite(10,HIGH);
   }else if (message == "65 8 3 0 ffff ffff ffff"){
     Serial.println("Right Button");
     digitalWrite(11,HIGH);
   }else if (message == "3"){
     Serial.println("Self Check Page");
     digitalWrite(7,HIGH);
   }else {
    Serial.println("INVALID INPUT");
    digitalWrite(4,LOW);
    // Ride Screen  
    digitalWrite(5,LOW);
    // Options Screen
    digitalWrite(6,LOW);
    // Self Check Screen
    digitalWrite(7,LOW);
    // Music Screen
    digitalWrite(8,LOW);
    // Music Left
    digitalWrite(9,LOW);
    // Music Play Pause
    digitalWrite(10,LOW);
    // Music Right 
    digitalWrite(11,LOW);
   }
    Serial.println(message); //...print it out
  }


}


void resetAll(void){
    digitalWrite(4,LOW);
    // Ride Screen  
    digitalWrite(5,LOW);
    // Options Screen
    digitalWrite(6,LOW);
    // Self Check Screen
    digitalWrite(7,LOW);
    // Music Screen
    digitalWrite(8,LOW);
    // Music Left
    digitalWrite(9,LOW);
    // Music Play Pause
    digitalWrite(10,LOW);
    // Music Right 
    digitalWrite(11,LOW);
  Serial.println("Reset All Lines");
}

 

 

Further Here are some Code snippets for my Perodic function checking the Arduino Lines

DEFINING THE BUS


DigitalIn  dispBoot(PC_4);            // Connected to D4 :: Display Boot Sucessful  
DigitalIn  mPnP(PB_1);            // Connected to D10 :: Music PLay n Pause
DigitalIn  mRt(PB_2);            // Connected to D11 :: Music Rt
DigitalIn  rideS(PB_11);            // Connected to D5 :: Ride Screen
DigitalIn  bumpP(PB_12);            // Connected to D6 :: Bump Pressed
DigitalIn  scS(PB_13);            // Connected to D7 :: Self Check Screen
DigitalIn  musicS(PB_14);            // Connected to D8 :: Music Screen 
DigitalIn  mLt(PB_15);            // Connected to D9 :: Music Left




 

Checking the bus in Preodic()

// Screen and Controlls Checks
    if(dispBoot){
        nextionBoot = true;
        nextionScreen ='B';
    }else if(rideS){
        nextionScreen ='R';
    }else if(bumpP){
        nextionScreen ='B';
    }else if(musicS){
        nextionScreen ='M';
    }else if(scS){
        nextionScreen ='S';
    }
    
    if(mPnP){
        nextionMusic ='P';
    }else if(mLt){
        nextionMusic ='L';
    }else if(mRt){
        nextionMusic ='R';
    }
    
    //Update the Display Screen
    if(nextionScreen =='R') {             // checking if nextio display is on rise screen
        nextion.printf(dispSpeed);                                   // updating Speed Value on Nextion Display
        nextion.printf("%d",(int)(ridingSpeed));
        nextion.printf("%c%c%c",terminator,terminator,terminator);
        
        nextion.printf(dispAvg);                                   // updating Avg Speed Value on Nextion Display
        nextion.printf("%d",(int)(avgSpeedF));
        nextion.printf("%c%c%c",terminator,terminator,terminator);
        
        nextion.printf(dispDist);                                   // updating Distance Value on Nextion Display
        nextion.printf("%d",(int)(totalDist));
        nextion.printf("%c%c%c",terminator,terminator,terminator);
    }else if(nextionScreen =='S' && scS){
        if(hum_temp->read_id(&id)){
            nextion.printf(hx_check);
            nextion.printf(pass);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
        }else {
            nextion.printf(hx_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
            nextion.printf(temp_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
        }
        if(press_temp->read_id(&id)){
            nextion.printf(bx_check);
            nextion.printf(pass);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
        }else{
            nextion.printf(bx_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
        }
        if(magnetometer->read_id(&id)){
            nextion.printf(temp_check);
            nextion.printf(pass);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
        }else {
            nextion.printf(temp_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);
        }
        if(accelerometer->read_id(&id)){
            nextion.printf(accl_check);
            nextion.printf(pass);
            nextion.printf("%c%c%c",terminator,terminator,terminator);   
        }else {
            nextion.printf(accl_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);   
        }
        if(acc_gyro->read_id(&id)){
            nextion.printf(gyro_check);
            nextion.printf(pass);
            nextion.printf("%c%c%c",terminator,terminator,terminator);   
        }else{
            nextion.printf(gyro_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);  
        }
        if(BLEStat){
            nextion.printf(ble_check);
            nextion.printf(pass);
            nextion.printf("%c%c%c",terminator,terminator,terminator);   
        }else{
            nextion.printf(ble_check);
            nextion.printf(fail);
            nextion.printf("%c%c%c",terminator,terminator,terminator);  
        }
    while(scS);
    }
    

 

Thanks For Watching

 

Regards,

GS Gill

Hey Guys, another SHORT UPDATE , I have somehow managed to get the button interrupts working yayyyyy with the BLE Code So now I can go further  

Here is a video demonstrating updation of Nextion display based on the Hall Sensor Data and some Computations.

 

 

Code Snippets

1. Define Global Timer Object

          Timer tick;

2. in Main()

        stopC = 1;                         // skips calculation of speed if set to : 1

         BLEStat = 0;

         hallSensorCounter = 0;

         hallSensor.fall(&irqcallback_hallSensor);   // interrupt

3.  In ISR

         stopC = 0;                        // enables calculation of Speed

         timex = tick.read_ms();

         hallSensorCounter++;

         tick.reset();

         //hallSensor.enable_irq();

4.  In periodic function computing the speed Dist and other details

        if (tick.read_ms() > 10000) { //(tick.read_ms() < 100 || tick.read_ms() > 10000 )       // check if bike is ideal standing ..

             stopC = 1;

         } else  stopC = 0;

 

         if (stopC == 0) {

            timex = timex * 100 * 60; //min

             ridingSpeed = (2 * M_PI * cycleTyreRadius) / timex ;   //  in mtr/sec

         } else if(stopC == 1) {

             ridingSpeed = 0;

         }

   

         totalDist = 2* M_PI * cycleTyreRadius * hallSensorCounter;     // calculating total distance

 

         avgSpeed[avgCtr] = ridingSpeed;

         avgCtr++;

         if(avgCtr == 4) avgCtr = 0;

 

         for(int i = 0; i == 4; i++) {    // calculation of avg speed

             avgSpeedF += avgSpeed[i];

         }

         avgSpeedF = avgSpeedF/5;

 

 

Thanks for Reading

 

Regards,

GS Gill

Hey Guys, While working on the Battery decisions in my previous Blog I came across a huge issue of power consumption.

 

Let's see how - taking into consideration the following

1.     Avg Current consumption - ~15mA for the STM32 Nucleo and ~105mA for the Display (Considering 15mA to be insignificant)

2.     So with a 3000mAH battery and about 110mA load  Running time = 3000/110 * 0.7. == ~19 Hours

3.     Now if somehow I can reduce the avg current consumption to half then the runtime will be doubled HeheheHAHAHAHA PPPOOOWWWeeeRRRR !!! (Just wondering how many of you remember Powerpuff girls )

 

Lets see my solution in detail, On any normal LCD display the maximum power consumption is due to he LED's which contribute to about 85% of power consumption.

Now lets see if we can control the brightness Referring to the Nextion Instruction Set  -- dim command dims the display where if we set dim to 0 it will switch off the LED's just perfect moreover thsp & thup can set the display in sleep mode and wake it respectively.

 

Now in my GUI, The maximum time someone will spend is on the RIDE Screen, but I cannot make it absolutely BLANK / 0 brightness. so I have implemented a Slow dim mechanism wich will smoothly dim the display to a point where the contents are visible and you can get to max brightness just by one tap , The same is also been implemented on Music Controls Screen.

 

On all other screens I have a timeout there the display enters low power mode, shutting down the LED's as well and one can wake it back up by just a tap.

 

The implementation and power savings can been seen in below VIDEO

 

 

with this instead of ~110mA we will be consuming about ~40 mA if on ride screen for on an Avg that for the given battery I am using will give about ~32 Hours of on Time    that gives us additional ~10-12 Hours

Hurrayyyyyyyyyy...

 

 

Thanks for Reading

Regards,

GS Gill

Hey guys welcome to another IoTonWheels design challenge blog of project SbSr. Lets talk about powering my project at this stage and learn more about various approaches I followed and issues I faced

 

So the first challenge was to finalise a power source, obviously the battery, and to fix that lets first find out the power requirement of the system. Luckily there is a IDD measurement jumper int the STM32 Nucleo Board which will give us a good estimate of the power consumed by the STM32 Hardware.

 

Next I tried measuring the entire system power rt from the source which came out to be about 14 mA; Next came the major power hungry device the Display who had about 105mA of power consumption

So totalling it all the system would consume about 130 mA on an average pace. So to run this for about 10 hrs approx 1300mAH battery would be required if my calculations art bad

below are few batteries I had and tested

Next comes charging solutions, for which I had the following options laying

1 & 2 are based upon cheep TP4506 IC with battery protection circuit and reverse polarity protection as well as under/over voltage protection.

next three images are of Groove Solar /kit which I later dropped to use because of max 3.3v VCC but I needed 5V for the Hall sensor to work

After doing some trials with all of the above I have selected The Setup Below

Due to the Following Reasons .

     It is a massive 3000mAH battery So, It would run the system for 17-19 Hours, and after some Nextion display Battery savings More than a Day (Will Cover the Later in next Blog Post )

     It uses a TP4506 Battery Charging Ckt with protection circuits.

     A XL6009 Boost Convertor 3W (So at 5V we will get a Max of 600mA which is good for a ~200mA Load)

     A Push button switch was added for reduction in power wasted by the boost convertor

     2 Pin JST for connecting the battery to virtually anything

 

Thanks for Reading

 

Regards,

GS Gill

Hey guys, Here is an another update on sending dummy sensor value and outputting the data to the Nextion Display.

 

SEE THE VIDEO

 

SENDING DATA TO NEXTION DISPLAY

So, How do one send data to sexton display using STM32,

 

Lets go through the Nextion instruction set where we will se that in  the display there are concepts of Objects such as text object, button object , etc.

each of the objects have certain properties like colour, text, value, etc ... ..

so the way we send the values

 

is Obj_Name.Obj_Property=Value followed by termination charter

for example, if my number display object is n0 and it has a property value val

 

so the expression to be sent to Nextion display would be

n0.val=20 followed br termination sequence.

 

Termination Sequence

termination sequence of sexton displays is 0xFF three times , i.e. 0xFF 0xFF 0xFF

 

 

My Code implementation

Defining strings

static const char terminator = 0xFF;       // Nextion termination sequence

char* dispSpeed = "n0.val=";                              // Nextion RIDE screen commands

char* dispAvg = "n2.val=";

char* dispDist = "n1.val=";

 

in functions

 

nextion.printf(dispSpeed);                                   // updating Speed Value on Nextion Display

nextion.printf("%d",(int)(ridingSpeed));

nextion.printf("%c%c%c",terminator,terminator,terminator);

      

which successfully update the display

 

Thanks for reading

GS Gill

Hey Guys Welcome to yet another Very Short UPDATE Blog Post on Smart Bike Smart Rider Project for IoTonWheels Design Challenge. In this Blog Post I will Go through testing and setting up the Hall effect Sensor With the STM32 Board using mBed Toolchain.

 

So in the last post we had fabricated our sensor board Now lets interface it

In this image Pin one on Top is the Vcc (+3.3V), Middle is GND and Bottom is Vo (i.e Signal pin)

So the sensor by defaults Outputs a High i.e. Logic 1 when no external Magnetic element is found, and Outputs a Low, i.e. Logic 0 when South (SOUTH) pole of the magnet crosses close to the sensor.

 

In my first test I created a Stand Alone Application to test the above functionality using Interrupts as that is what I want

 

<CODE>

#include "mbed.h"

 

DigitalOut myled(LED1);

 

InterruptIn hallSensor(PA_12);

// Hall Sensor Vout Connected to P8. and GND and VCC Connected to GND and +3.3v Respectively

 

// pb Interrupt routine - is interrupt activated by a falling edge of pb input

void hallSensor_ISR (void) {

    myled = !myled;

}

 

int main() {

    hallSensor.fall(&hallSensor_ISR);

    // Blink myled in main routine when the Int occurs

    // via interrupts that activate hallSensor_ISR routine

    while (1) {

    }

}

<CODE ENDS>

 

NOTE : I will do a blog on introduction and playing with mBed platform for now I wanted to keep this one very short and crisp

 

To my surprise the code worked In first attempt and I had tears of Joy coming from my eyes. (No I am not a CryBaby This was the First time something Worked with ST and mBED !!)

 

Regards,

GS Gill

 

P.S. As usual, any comments of your's is a valuable Feedback and a potential scope of improvement of content I publish.

First of All, Another pic of my photography skills

Ok, after admiring the golden sand, lets come to the point. In my previous Blog I had mentioned about Hall effect sensor and how I have tested the design and finalised it for my project.

 

In this blog I will walk through the process of getting a more permanent prototype to play with. So, lets get started with the Easiest way to Homemake PCB's of What I would like to call the Poor Artist's way of PCB Prototyping

 

Now you may Ask Why Not Purf Board / Zero PCB / Prototype PCB ? Well Because of the following Reasons.

1.     I have a Cheep Chinese soldering Iron and it gets rid of the pads All together

2.     The Purf boards, are mechanical week specially for the Size I am planning. So, When I plan to use cable tied and tight it to the cycle frame the board will break. (I am HULK)

I will go through the process of in house Fabricating the PCB and testing it. Tools Required are listed as under

 

What is Needed Where can it be foundHow Much :/
Quantity Required
Single Side Coper PCBCan be found on eBay/Amazon/Local Store the last being the cheepest20-100 INRSmall piece of about 1.5x3cm
A Permanent MarkerMost Common places are (Your Boss's DESK, School teachers room, with a lab assistant), I would prefer a stationary shop 20 INROnly 1x Black Colour Needed
Aftershave Most commonly found in a washroom or with your dad 60 INR
Ferric chloride CrystalseBay / Amazon, Local dealer120 INR50/100 gms is more than enough
Water everywhere FREEat least 1Ltr
Paper CutterCommon that you should have 40 INROnly 1
Rough paper and PenThat you Must have FREEas per your wish
Surgical Gloves Medical Store or Friendly neighbourhood doctor30-60 INRone pair is good enough

 

So, Lets Get Started with Fetching a Glass Jar (Preferably Heat resistant) and come powder of Ferric Chloride. Mix them in 1:5 parts of FeCl3:H2O.

NOTE This is a EXOTHERMIC Reaction so do it deliberately. Add the crystals first then mix water slowly.

NOTE FeCl3 is extremely irritating so use Gloves.

-->+Water ==

 

Second Step is cut the Copper Board using paper cutter; Make grooves in front as well as Back and simply snap them. to get the pieces as shown in the image. After snapping, take a dish scrubber and gently scrub the copper surface till it is shiny.

Third step is to feet the components you want to use on a piece of paper and mark the leads on paper, then draw the connections on the paper.

NOTE DONT CRISS CROSS The connections, they will come up as shorts In final design.

P.S. You can also be more artistic by making designs and writing texts. as you can see below in image

Fourth step is Etching. Take the Solution created and place the board upside sown. I.e. the shiny side inside the solution and let the board float on the liquid, Do regularly check the echoing process by removing board and inspecting. Keep etching till you can no longer see the copper.

NOTE while etching, the places you had drawn using marker will be intact and rest of the copper will slowly turn into a mate copperish look.

Fifth STEP is cleaning. I used a AfterShave for this as it has high concentration of Alcohol (One of the universal solvent) and it smells Awesome

Pre Final STER is to check the board for stupidity \

As you can see in the Images below I had Written SbSr right where my Hall effect sensor would come an di was stupid enough to remove the marker from it exposing the copper. So I had to use some Insuating tape to hide the text Stupid me.

Final step is to Solder the board and test Get your cheep ass soldering station and get on to it.

I made another one just out for redundancy. Below are some other boards I made while testing

 

So with the PCB's sucessfully fabricated, it time to test them Tune on for next post on that

 

Regards,

GS Gill

Hello Guys Another pic of my Photography Skills

Yo !!

 

Ok, So coming on to the topic.

 

Homemade Smart Cycle Computer - Finalising Sensor's and INTERFACE

So, A Part of the project was to get a System of measuring the Speed, Distance travelled, Avg Speed, etc. In this blog I will review various mechanisms I tried and Which one worked the best

 

OK, Many of us are used to the Cycle computers the small little thing that tells us some important Information like The Speed, Distance and so on. . .

Or the One I was Eying For (As a prize from Element14)

 

I Tried getting my self one of those cheep ones and trying to Rip it apart. Unfortunately It seemed a lot more complex and I immediately realised that It will take a lot of effort to reverse engineer so I dropped and decided to explore how can we achieve the task.

 

Method - I Using a Limit Switch

The easiest method I came up with is using a Limit switch something like this

 

 

The Idea was to tie a small wooden piece to the spokes of the tire and the limit switch to the tyre frame so when ever the tyre rotates, it will press the switch and the same will be recorded in software

Unfortunately, I realised its the most stupid IDEA.

Why ??

Because, primarily The switch has limited click's and is prone to wearing as it contains mechanical parts.

 

Method - II Using Reed Sensor

Next, My GENIUS mind came up with a magnetic solution as these sensor were cheep in market (about 5-10 INR / couple of cents) and Internet blames these to be Magnetic switches.

So I grabbed few from market, made a small board for them as they are pretty delicate and started testing. Here's How they Work:

 

Well It does act as a Switch but with a very poor response, It took couple of milliSec for the switch to detect the magnet thus making the entire fast detection thing pretty much useless and another Fail exercise for the job.  

 

Method - III Using Hall effect Sensor (FINAL Method)

Well, we all love INTERNET and my Google Searching Skills payed off When I came across This beautiful device called as Hall effect Sensor , My eyes sparkled while going through the data sheet and my gut said; This is it.

 

and so I went miles to fetch one of these babies (Well eBay did all the travelling credit to them ) and I received the beautiful sensor. I immediately ripped the package grabbed a Yun, breadboard and couple of wires. After few minutes of a basic Arduino Sketch I was able to achieve what I wanted. A fast magnetic way to get the job done.

 

This is a Roucg Circuit Diagram

 

Click here for the Datasheet

 

HERE IS A VIDEO OF ME TESTING THE SETUP

 

Note : Few things in this video are recycled and are readily available for makers.

and you with couple of basic prying tools can get all required components easily from a Old DVD/ CD Writer. They use the Magnets near the lens assembly to move it and the Hall sensors beneath the spindle to sense the spin speed. 

 

 

Part List

Allegro A1104 Hall Sensor

10K Resistor

Bread Board

Couple of Single Strand Wire

Arduino development kit (Any Will Work I have tested using Yun)

 

Conclusion

In conclusion,

1.    This was more like an tutorial/ How to approach a problem given some constraints BLOG, So please do provide feedback if you guys think that it is a bit too kidish

2.    The prototype of Hall effect Sensor looks great and its time to get it to next stage. Lets design a PCB for the sensor Board and none of the CAD stuff, lets get a bit creative and test our drawing skills ;

  PREVIOUS BLOG

  NEXT BLOG

 

Hello everyone, Sorry for delay in blogs, I was in transit and I am currently located HERE So It Kinna difficult to stay connected to the world.

Moving on, as the part of the Challengers Kit we received the following Hardware,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

But first lets go through the Unboxing Video sorry for camera orientation

   UNBOXING VIDEO

 

{tabbedtable} Tab LabelTab Content
STM32L476RG NUCLEO

 

The Main processor board

The board is based on STM32L476RG MCU which boasts

    ARM® 32-bit Cortex®-M4 CPU with FPU & ART Accelerator @ 80MHz

     1MB Flash memory

     128KB SRAM

    USB OTG 2.0 full-speed

    RTC with HW calendar, alarms and calibration

    24 capacitive sensing channels

    16x timers

    1x USER LED

    1x USER LED

    Arduino style headers + ST Morpho connectors (20x2 +20x2 Headers)

    ... And many more DATASHEET Download

 

 

For more details ON Development Board Click Here

Click here for info on the MCU

BLE Expansion Board

 

BLE Expansion Board - X-NUCLEO-IDB05A1X-NUCLEO-IDB05A1

frontback

This Board is based on SPBTLE-RF BlueNRG-MS RF module and connects to the main Controller board over SPI BUS and Interrupts. It has Arduino comparable connectors and can be used with a Arduino comparable board.

 

The Kit is FCC Certified so you are goos to get the same in the final product.

fcc

And I am a huge fan of the Star Ground Pad on the 2x20 Header

 

Click here for E14 product page

Click here for ST page

Sensor Expansion Board

 

MEMS Sensor Expansion Board X-NUCLEO-IKS01A2X-NUCLEO-IKS01A2

frontback

This is a All in One Sensor package by ST which boasts the following

  ST LSM6DSL MEMS 3D accelerometer (± 16 g) and 3D gyroscope (±2000 dps) 

  ST LSM303AGR MEMS 3D accelerometer (±16 g) and 3D magnetometer (±50 gauss)

  ST LPS22HB MEMS pressure sensor, 260 - 1260 hPa

ST  HTS221HTS221 capacitive relative humidity and temperature sensor

  It also packs the Arduino Headers

 

It connects all the sensors on an I2C bus for easy connectivity. and features some advance configurations like Free Fall detection, Single/Double tap gesture detection with sensitivity adjustment,  Etc.

 

Click here for E14 product page

Click here for ST page

 

WiFi Expansion Board

 

WiFi Expansion Board X-NUCLEO-IDW01M1X-NUCLEO-IDW01M1

frontback

This is a WiFi Expansion board based on the SPWF01SA module. The module itself is an STM32 WiFi SoC seen in wafer package. It boasts

  512KB on chip memory

  1 MB program flash memory 

   Integrated TCP/IP, TLS/SSL

   AT command set host interface

 

Click here for E14 product page

Click here for ST page

 

 

Moving on.

First Impressions

The unboxing of the package was more like a Squashed fruit opening, with the box completely crushed and the pins of the board somewhat damaged (nothing a powerful nail couldn't fix)

after some Nailing

 

So I moved on and Seams like there is a lot go GunK on the PCB's. Eeeyyuuuu .. .. ....

back

And yes the Yellowish part on the headers is factory flux

 

The WiFi Expansion board has ST Morpho connectors as only one side headers !!

 

 

Thanks for reading, More coming soon !!

Ohh I forgot This.

goodluck

Thanks rscasny, for this lovely card.

//GS Gill

 

  PREVIOUS BLOG

  NEXT BLOG

BLOG - II 

NexTion - Enhanced Heven

GS Gill - 11 October 2017

As usual please download the attached PDF for better formatting .

    PREVIOUS BLOG

    NEXT BLOG

Table of Contents

 

1. What is Nextion Display 

2. Getting Started With the Display

3. Project implementation  (Click here for Project Implementation Video)

4. Way forward

 

 

 

What is Nextion Display

From Nextion web : HERE

 

“Nextion offers a new and easy way to interface, help to make GUI easier. Available from 2.4″ to 7″ models, provides a analog touch screen operator interface with programmable function buttons, gauges, progress bars…etc., Nextion is an interface solution designed to complement your application needs.

 

But for us makers : It is a Display solution which makes GUI designing and Interfacing with the Main Embedded System so much easier, plus It Offloads the display subsystem to a co processor.

 

They are available in all sizes and capabilities See the available option below

 

I got the display from banggood.com HERE and it took about 20 Days to get delivered.

 

Key Benefits & Disadvantages

  • Offloads the entire Display programming, Image Conversion, Image Array storage, etc .. .. to the Nextion Display.
  • Easy to design GUI
  • Easy interface with UART, instead of I2C or SPI.
  • Inbuilt Graphics memory
  • Inbuilt 4-Wire Resistive touch and interface
  • Event based Programming
  • Inbuilt RTC & EPROM
  • 8 GPIO’s can offload Button Navigation Interface
  • And Many More.. .. ..
  • Power Hungry (Giving power to one more micro controller)
  • Only way to upload new GUI design is either Serial (Slow) or Via SD Card (repetitive)
  • Each time there is a rev in the GUI, The on board flash of the MCU has to be reprogrammed
  • Nextion Editor IDE Works only on Windows

 

 

That being said, lets look at the available options below ( Source : Click Here )

 

Getting Started

OK, So getting started with the display is as simple as  1, 2, 3, 4.. 5

and

Wooooo oo ooooo, Yaaaayyyyyyyy.   !!! !!! !!! !!!!

 

1.     Well first Lets get a Nextion Display (check the link below)

2.      Lets get the Nextion Editor (again Check the link below)

3.     Select your Display

4.     Make your design using GUI editor, Compile and copy the *.tft file from nextion built folder

5.     Copy the *.tft into SD card, insert the SD card into the Display and power it on. Let it uploads the sketch onto the display’s memory and remove the SD card. Re-Power the display and Enjoy.

 

Project implementation

Here is a video of my implementation, any reviews and comments would be appreciated.

 

 

Way forward

AS of now interface with the MCU is a huge ISSUE !!

 

Updates:-

30 Sep 17 UART Interrupt not working

01 Oct 17 Button Interrupt works

08 Oct 17 All Interrupts somehow stopped Working. :’(

08 Oct 17 Since.. I HATE MBED

 

As the Rx Interrupt is not working and now even the TX button Interrupt is not working it is useless working with mbed platform .

 

Trying to download STM32 Openware to try my luck there .

 

 

Links & References

1. Nextion Home Page

2. Nextion Buy Page

3. I got it from here

4. NX4024K032 Module Wiki

5. Nextion Instruction Set

6. And the New Instruction Set Page

 

 

    PREVIOUS BLOG

    NEXT BLOG

BLOG - I

Smart Bike Smart Rider (SbSr)

GS Gill - 24 September 2017

NOTE : For a better formatted version please check the attachment.

Click the Youtube Button for IoTonWheels Design Challenge SbSr Project Playlist

https://www.youtube.com/playlist?list=PLnp4Q6KlcA9lsg305T_LPAd7MFnrqGo5f

    NEXT BLOG

Table of Contents

 

1.            Introduction to the project     

2.           Plan of the project

2.           Physical Device Concept

3.           Overall System 

              a.           Display Subsystem

              b.           Sensors SubSystem

              c.           BLE Subsystem

              d.           Battery subsystem

4.          Blogs ( will update subsequently )

 

 

Introduction

Welcome to Smart Bike Smart Rider (SbSr) Project. This is the first out of many more blogs yet to come.

Sneek Peak Of what is to come

Firstly, Let me introduce you to SbSr. 

 

Ok, so SbSr is not just a IoT project but a assistant or a personal touch that you own bicycle will give you. The concept is to make you bike more than just bike, more like a friend.

 

The genesis of the project comes from a overall shift in trend towards motorised vehicles rather than riding bicycles. Bicycles are now a small community of riders who enjoy riding or a a professional community who train for excellence.

 

There is a overall shift in fitness trend with introduction to Smart Wearables like FitBit, pebble, Xi Band, etc. But still, If you want to go to gym, you most probably would go on a motorbike or a car, even if its just half a mile away.

 

This project aims to take the best of technology, gel it together and make a product which would help start a trend of biking (as another fitness measure) just as the Wearables Electronics did, Fitness trend.

 

With the brief introductions lets dive deep into how am I planning to achieve this.

 

 

The Secret Plan

So, Here is the plan,

  SORRY : But, due to less time available, as I have to move urgently off station to a remote location where its difficult to carry my modules and bike, I will try and finish the project by Mid next month.

 

I am planning to complete the project in the following parts - THE MANTRA

 

Part 1 - Getting ready with the GUI for the display

Part 2 - Getting the Battery subsystem working

Part 3 - Getting to learn and work with MBed :0

Part 4 - Getting to learn about BLE and MBed_BLE API

Part 5 - Writing sensor modules defn and logic

Part 6 - Interfacing the Sensor subsystem

Part 7 - Interfacing BLE and Testing

Part 8 - Interfacing Power subsystem

Part 9 - Interfacing Display Subsystem

Part 10 - Overall testing

Part 11 - Final Demo

 

I will be changing the colours of the parts I am currently working on and which are completed as per following

 

<Secret Colour Codes>       COMPLETED 

                                                         ALMOST_COMPLETED

                                                         IN_PROGRESS         

                                                         STARTED_WORKING    

                                                         NOT_EVEN_TOUCHED

Physical Device Concept

Please refer to the image below for concept of the device.

SbSr_Concept

 

Overall System

Please refer to the image below for Overall System diagram.

SbSr_System_design

 

Display Subsystem

 

As already mentioned I am planning to use a NEXTION Enhanced NX4024K032 3.2” Resistive Touch screen Module

 

- If you want to buy the display Click HERE

- For Nextion GUI Editor Click HERE

 

NOTE : Link for Display Subsystem Blog will be updated once I publish it

 

Sensor Subsystem

 

The Sensor Subsystem Blog Link

 

BLE Subsystem

 

BLE Subsystem Blog Link

 

Battery Subsystem

 

Powering the Beast Blog Link

Power Savings with NEXTION DISPLAY Blog Link

 

 

Blogs

BLOG 1 : Introduction to SbSr (Smart Bike Smart Rider)

BLOG 2 : NexTion - Enhanced Heven SbSrBLOG 2 : NexTion - Enhanced Heven SbSr

BLOG 3 : The Kit Arrives

BLOG 4 : Want a Homemade Smart Cycle Computer ? [ PART 1 ]

BLOG 5 : From BreadBoard prototype To Homemade PCB :: The Fastest Way  

BLOG 6 : Want a Homemade Smart Cycle Computer ? [ PART 2 ]

BLOG 7 : NexTion STM32 Interfacing Issues and Demonstration

BLOG 8 : Powering the Beast

BLOG 9 : Power Savings with NEXTION DISPLAY

BLOG 10 : Hall sensor working Fine with interrupts

BLOG 11 : Nextion Display Interface with STM32 NUCLEO [Completed]

BLOG 12 : Assembling the Setup on My Bike

BLOG 13 : The Accident

BLOG 14 : The Sensor Subsystem

BLOG 15 : BLE Subsystem

 

YOUTUBE PLAYLIST LINK for IoTonWheels Design Challenge by ST & Element 14 Community

 

 

 

I conclude my official submission for SbSr project HERE. I will update TWO more Blog on BLE and Sensor Subsystem and ONE complimentary Blog on introduction to ARM mBed platform.  I would like to thank the Judges, Readers for going through my content any feedback would be appreciated. I would also like to thank Element14 and ST for giving me a chance to project and pitch my IDEA and to participate in an full on manner

 

I am also regretful of the fact the due to time constraints I was not able to complete the project, But I have definitely put up the best I could have done .

 

Once again thanks and see you guys in another Design challenge .

 

Thanks for reading,

GS Gill

 

                                                                                                                                                                             NEXT BLOG