IoT-Enabled Electric Scooter Using Hexabitz Module

Revamp an electric scooter’s control system to be controllable and monitorable via an Android app and web server using HEXABITZ modules.

ExpertWork in progress2 days938
IoT-Enabled Electric Scooter Using Hexabitz Module

Things used in this project

Hardware components

SPST 12V/20A MOSFET Switch (H0FR7)
Hexabitz SPST 12V/20A MOSFET Switch (H0FR7)
×2
3.3V/1A DC-DC Power Supply Module (H03R00)
Hexabitz 3.3V/1A DC-DC Power Supply Module (H03R00)
×1
ESP32-C3 WiFi+BLE Module (H21R2x)
Hexabitz ESP32-C3 WiFi+BLE Module (H21R2x)
×1
SAM-M10Q GNSS (H1FR5x)
Hexabitz SAM-M10Q GNSS (H1FR5x)
×1
3-axis IMU and 3-axis Compass Module (H0BR40)
Hexabitz 3-axis IMU and 3-axis Compass Module (H0BR40)
×1
100-mil PTH Proto Board (H00R4x)
Hexabitz 100-mil PTH Proto Board (H00R4x)
×1
STLINK-V3MODS Programmer (H40Rx)
Hexabitz STLINK-V3MODS Programmer (H40Rx)
×1
Mounting Hole Module (T00R10)
Hexabitz Mounting Hole Module (T00R10)
×4
Vertical Extension (T00R2x)
Hexabitz Vertical Extension (T00R2x)
×1
4-Pin USB-Serial Prototype Cable
Hexabitz 4-Pin USB-Serial Prototype Cable
×1
BitzClamp
Hexabitz BitzClamp
×2
USB 2.0 A Male to Micro B Male Cable
×1
G30 Ninebot Max Motor
×1
Ninebot MAX G30 Control Board
×1
Thumb Brake Gas Speed Regulator for MAX G30D
×1
Data Control Cable Power Connection for Max G30 Ninebot
×1
G30D BMS Board
×1
Max G30 Li-Ion Battery Charger (external) YZ4205000
×1
Max G30 Li-Ion Battery Charger (Built-in) SKT-Max0052
×1
3.7 Volt 3500mAh 18650 Lithium Battery (2Pack)
×20
XT60 Connectors
×1
0.1x8mm Pure Zinc Strip
×1
103mm Battery Wrap
×1
LM2596HV DC-DC Adjustable Step Down Buck Converter Power Module
×1
2.54 mm Male Female Dupont Wire Jumper with Pin Header Connector Housing Kit
×1
1x4 male pin header
×2
smd 0603 100ohm resistor
×4
100u 15v dip electrolytic capacitor
×1
smd 0603 200kohm resistor
×1
smd 0603 10k ohm resistor
×1
TVS DIODE 3,3V 10,9V SOD323
×2
smd 0603 100n capacitor
×1

Software apps and online services

VS Code
Microsoft VS Code
STM32CUBEPROG
STMicroelectronics STM32CUBEPROG
STMicroelectronics STM32CubeIDE
Android Studio
Android Studio
Microsoft visual studio 2022
Microsoft SQL Server

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free
3D Printer (generic)
3D Printer (generic)
Drill / Driver, Cordless
Drill / Driver, Cordless
Grinder Welder
Saleae 8-Channel Logic Analyzer

Story

Read more

Code

IMU Module Firmware

C/C++
main,c file
/*
 BitzOS (BOS) V0.2.9 - Copyright (C) 2017-2023 Hexabitz
 All rights reserved

 File Name     : main.c
 Description   : Main program body.
 */
/* Includes ------------------------------------------------------------------*/
#include "BOS.h"

/* Private variables ---------------------------------------------------------*/
float ax,ay,az;
uint8_t IMU_Buffer [30] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21};
uint8_t ready_msg = (uint8_t)'a';
uint8_t Mosfet2_msg;
uint8_t i=0,j=0;
uint8_t seconds1;
uint8_t* ptr = NULL;
uint32_t D_throttle_s,D_break_s,Tickstart1,Timeout1=100;
float D_throttle,D_break,A_throttle_val,A_break_val;
#define MOSFET1_UART &huart4

extern ADC_HandleTypeDef hadc;
/* Private function prototypes -----------------------------------------------*/

/* Main function ------------------------------------------------------------*/

int main(void){

	Module_Init();		//Initialize Module &  BitzOS



	//Don't place your code here.
	for(;;){}
}

/*-----------------------------------------------------------*/

/* User Task */
void UserTask(void *argument){


//		Bridge(P2, P4);
		ADCSelectChannel(3,"top");//3
		ADCSelectChannel(3,"bottom");//3
		HAL_ADCEx_Calibration_Start(&hadc);
		Tickstart1 = HAL_GetTick();


	// put your code here, to run repeatedly.
	while(1){

	if ((HAL_GetTick() - Tickstart1) > Timeout1){

		ReadADCChannel(3, "top", &D_throttle);
		ReadADCChannel(3, "bottom",&D_break);

		A_break_val = D_break*3.27/4095;
		A_throttle_val=D_throttle*3.27/4095;
		SampleAccG(&ax, &ay, &az);
		i=0;
		ptr = (uint8_t*)&ax;
		IMU_Buffer[i] =(uint8_t)'x';i++;//0
		IMU_Buffer[i] = *ptr;ptr++;i++;
		IMU_Buffer[i] = *ptr;ptr++;i++;
		IMU_Buffer[i] = *ptr;ptr++;i++;
		IMU_Buffer[i] = *ptr;i++;

		ptr = (uint8_t*)&ay;
		IMU_Buffer[i] = (uint8_t)'y';i++;//5
		IMU_Buffer[i] = *ptr;ptr++;i++;
		IMU_Buffer[i] = *ptr;ptr++;i++;
		IMU_Buffer[i] = *ptr;ptr++;i++;
		IMU_Buffer[i] = *ptr;i++;

	//	fill the throttle and brake values

		ptr = (uint8_t*)&A_throttle_val;
		IMU_Buffer[i] = (uint8_t)'t';i++;//10
		IMU_Buffer[i] = *ptr;ptr++;i++;//11
		IMU_Buffer[i] = *ptr;ptr++;i++;
		IMU_Buffer[i] = *ptr;ptr++;i++;
		IMU_Buffer[i] = *ptr;i++;

		ptr = (uint8_t*)&A_break_val;
		IMU_Buffer[i] = (uint8_t)'b';i++;
		IMU_Buffer[i] = *ptr;ptr++;i++;
		IMU_Buffer[i] = *ptr;ptr++;i++;
		IMU_Buffer[i] = *ptr;ptr++;i++;
		IMU_Buffer[i] = *ptr;i++;
		IMU_Buffer[i] = (uint8_t)'e';i++;
//		j=0;
		HAL_UART_Transmit(MOSFET1_UART, IMU_Buffer, 21, 0xffff);
//		}
		Tickstart1 = HAL_GetTick();
	}
}
}
/*-----------------------------------------------------------*/

MaxG30_DashBoard.c

C/C++
/*
 * DashBoard.c
 *
 *  Created on: Jul 22, 2023
 *      Author: Ibrahim
 */

#include "MaxG30_DashBoard.h"
#include "GPS_Hardware.h"
#include "MaxG30_Common.h"
#include <string.h>

/*Private Macros */

#define DashBoardIndex 0x00 //fixed
#define ThroVolt_ConvRatio 73.58 // (195/2.65) where Speed[(21k/h)] >>> throttle hal_sensor voltage (2.55V) >>> Speed_Reg = 195 (decimal)//vdd = 3.28 V
#define Brake_ConvRatio 77.36 // (205/2.65)
#define Standby_AnalogVolt 0.9
#define AnalogVolt_Error 0.05
#define IMU_Buffer_N 49
#define ThrottleByte_N	8
#define BrakeByte_N 	9
/*************************/

/*************************/

/*Private Variables */

uint8_t DashBoardMessage[14] = {0x5A,0xA5,0x05,0x21,0x20,0x65,0x00     ,0x04,0x27,0x23,0x02,0x00,0xF1,0xFE};
float A_throttle_val=0.85,A_brake_val;
extern uint8_t IMU_BufferCpy[50];
extern uint8_t IMU_Buffer[50];
int i;
uint8_t *t_ptr=NULL;
uint8_t Speed_Reg,Brake_Reg;
uint8_t BrakeFlag;
extern DashBoard_Status DashBoard_state;

/*************************/

/*Private Functions Definitions*/

void CalcSpeedandBrakeRegValues();
void Update_throttle_and_brake_values();

/*************************/


void DashBoardRun(){
  
	Update_throttle_and_brake_values();
	CalcSpeedandBrakeRegValues();
	addCRC(DashBoardMessage, 14);
	SendFullDublexMessage(DashBoardMessage,14);
}

void Update_throttle_and_brake_values(){

	for(i=0;i<(IMU_Buffer_N);i++)
	{
		IMU_BufferCpy[i]=IMU_Buffer[i];
	}


	//search for throttle value
	for(i=0;i<(IMU_Buffer_N-5);i++)
	{
		if(IMU_BufferCpy[i]=='t'&&IMU_BufferCpy[i+5]=='b'){
			t_ptr = (uint8_t*)&A_throttle_val;
			*t_ptr=IMU_BufferCpy[i+1];t_ptr++;
			*t_ptr=IMU_BufferCpy[i+2];t_ptr++;
			*t_ptr=IMU_BufferCpy[i+3];t_ptr++;
			*t_ptr=IMU_BufferCpy[i+4];
			break;
		}
	}


	//search for brake value********************
	for(i=0;i<(IMU_Buffer_N-5);i++)
	{
		if(IMU_Buffer[i]=='b'&&IMU_Buffer[i+5]=='e'){
			t_ptr = (uint8_t*)&A_brake_val;
			*t_ptr=IMU_Buffer[i+1];t_ptr++;
			*t_ptr=IMU_Buffer[i+2];t_ptr++;
			*t_ptr=IMU_Buffer[i+3];t_ptr++;
			*t_ptr=IMU_Buffer[i+4];
			break;
		}
	}

}

void CalcSpeedandBrakeRegValues()
{

if(A_throttle_val<Standby_AnalogVolt)
	Speed_Reg = Zero_Speed_RegValue;
else
	Speed_Reg = A_throttle_val*ThroVolt_ConvRatio;

DashBoardMessage[ThrottleByte_N]=Speed_Reg;

if(A_brake_val<Standby_AnalogVolt)
	{Brake_Reg = Zero_brake_RegValue;BrakeFlag=0;}
else
	{Brake_Reg = A_brake_val*Brake_ConvRatio;BrakeFlag=1;}


DashBoardMessage[BrakeByte_N] = Brake_Reg;

}

MaxG30_Master control.c

C/C++
/*
 * MaxG30_Master control.c
 *
 *  Created on: Jul 25, 2023
 *      Author: Ibrahim
 */

#include "MaxG30_Master control.h"
#include "GPS_Hardware.h"
#include "MaxG30_Common.h"
#include <string.h>
/*Private Macros */


/*************************/

typedef struct{
	uint16_t CNB_INF_ERROR_REG;
	uint16_t NB_INF_BOOL_REG;
	uint16_t NB_INF_WORKMODE_REG;
	uint16_t NB_INF_BTC_REG;
	uint16_t NB_INF_ACTUAL_MIL_REG;
	uint16_t NB_INF_PRD_RID_MIL_REG;
	uint16_t NB_INF_SPEED_REG;
	uint16_t NB_INF_RID_MIL_L_REG;
	uint16_t NB_INF_RID_MIL_H_REG;
	uint16_t NB_INF_RID_MIL_SIG_REG;
	uint16_t NB_INF_RUN_TIM_L_REG;
	uint16_t NB_INF_RUN_TIM_H_REG;
	uint16_t NB_INF_RID_TIM_L_REG;
	uint16_t NB_INF_RID_TIM_H_REG;
	uint16_t NB_INF_RUN_TIM_SIG_REG;
	uint16_t NB_INF_RID_TIM_SIG_REG;
	uint16_t NB_INF_BODY_TEMP_REG;
	uint16_t NB_INF_BAT1_TEMP_REG;
	uint16_t NB_INF_BAT2_TEMP_REG;
	uint16_t NB_INF_MOS_TEMP_REG;
	uint16_t NB_INF_DRV_VOLT_REG;
	uint16_t NB_INF_MOT11_CURT_P_REG;
	uint16_t NB_INF_AVRSPEED_REG;
	uint16_t NB_CTL_LIMIT_SPD_REG;
	uint16_t NB_CTL_NOMALSPEED_REG;
	uint16_t NB_CTL_LITSPEED_REG;
	uint16_t NB_CTL_WORKMODE_REG;
	uint16_t NB_QUK_CRT_LIMIT_SPEED_REG;
	uint16_t NB_QUK_SYS_POWER_REG;
	uint16_t BAT_CAPACITY_REG;
	uint16_t BAT_TOTAL_CAPACITY_REG;
	uint16_t BAT_DESIGN_VOLTAGE_REG;
	uint16_t BAT_CYCLE_TIMES_REG;
	uint16_t BAT_CHARGE_TIMES_REG;
	uint16_t BAT_CHARGE_CAP_L_REG;
	uint16_t BAT_CHARGE_CAP_H_REG;
	uint16_t BAT_OVER_DISCHARGE_TIMES_REG;
	uint16_t BAT_FUN_BOOLEAN_REG;
	uint16_t BAT_REMAINING_CAP_REG;
	uint16_t BAT_REMAINING_CAP_PERCENT_REG;
	int16_t BAT_CURRENT_CUR_REG;
	uint16_t BAT_VOLTAGE_CUR_REG;
	uint16_t BAT_TEMP_CUR_REG;
	uint16_t BAT_BALANCE_STATU_REG;
	uint16_t BAT_ODIS_STATE_REG;
	uint16_t BAT_OCHG_STATE_REG;
	uint16_t BAT_CAP_COULO_REG;
	uint16_t BAT_CAP_VOL_REG;
	uint16_t BAT_HEALTHY_REG;
	uint16_t BAT_CORE_VOLT_1_REG;
	uint16_t BAT_CORE_VOLT_2_REG;
	uint16_t BAT_CORE_VOLT_3_REG;
	uint16_t BAT_CORE_VOLT_4_REG;
	uint16_t BAT_CORE_VOLT_5_REG;
	uint16_t BAT_CORE_VOLT_6_REG;
	uint16_t BAT_CORE_VOLT_7_REG;
	uint16_t BAT_CORE_VOLT_8_REG;
	uint16_t BAT_CORE_VOLT_9_REG;
	uint16_t BAT_CORE_VOLT_10_REG;
	}MaxG30_Master_Control_Registers;

/*Private enums */

typedef enum MasterControlMemoryRegisters {
	CNB_INF_ERROR = 0x1B, //Error code
	NB_INF_BOOL = 0x1d, // Boolean state word [4]
	NB_INF_WORKMODE = 0x1F, //Current operation mode, 0 NORMAL;1 ECO; 2 SPORT
	NB_INF_BTC = 0x22, //Battery percentage of the scooter , 0-100
	NB_INF_ACTUAL_MIL = 0x24, //Actual remaining mileage, unit: 10m
	NB_INF_PRD_RID_MIL = 0x25, //Predicted remaining mileage, 10m
	NB_INF_SPEED = 0x26, //Current speed, 0.1km/h
	NB_INF_RID_MIL_L = 0x29, //Lower 16 bits of the total mileage, m
	NB_INF_RID_MIL_H = 0x2A, //Higher 16 bits of the total mileage, m
	NB_INF_RID_MIL_SIG = 0x2f,//NB_INF_RID_MIL_SIG
	NB_INF_RUN_TIM_L = 0x32, //Lower 16 bits of the total operation time, Sec
	NB_INF_RUN_TIM_H = 0x33, //Higher 16 bits of the total operation time, sec
	NB_INF_RID_TIM_L = 0x34, //Lower 16 bits of the total riding time, sec
	NB_INF_RID_TIM_H = 0x35, //Higher 16 bits of the total riding time, sec
	NB_INF_RUN_TIM_SIG = 0x3a,//Single operation time, sec
	NB_INF_RID_TIM_SIG = 0x3b,//Single riding time, sec
	NB_INF_BODY_TEMP = 0x3E, // Scooter temperature, 0.1
	NB_INF_BAT1_TEMP = 0x3f, //Battery 1 temperature, 0.1
	NB_INF_BAT2_TEMP = 0x40, //Battery 2 temperature, 0.1
	NB_INF_MOS_TEMP = 0x41, //MOS pipe temperature
	NB_INF_DRV_VOLT = 0x47, //System driving voltage, 0.01V, also supply voltage of the central control
	NB_INF_MOT11_CURT_P = 0x53, // Motor  phase current, 0.01A
	NB_INF_AVRSPEED = 0x65, // Average speed, 0.1km/h
	NB_CTL_LOCK = 0x70, // Lock [5], send 1 for locking, scooter reset automatically
	NB_CTL_UNLOCK = 0x71, //Unlock [5], send 1 for unlocking, scooter reset automatically
	NB_CTL_LIMIT_SPD = 0x72, //Speed limit or speed limit release
	NB_CTL_NOMALSPEED = 0x73, //Speed limit value in normal mode, 0.1km/h
	NB_CTL_LITSPEED = 0x74, //Speed limit value in speed limit mode, 0.1km/h
	NB_CTL_WORKMODE = 0x75, //Operating mode: 0, NORMAL; 1,ECO; 2, SPORT
	NB_CTL_ENGINE = 0x77, //Start or shut down the engine
	NB_CTL_REBOOT = 0x78, //Restart system [6], write 1 for restart
	NB_CTL_POWEROFF = 0x79, //Shutdown [6], write 1 for shutdown
	NB_QUK_CRT_LIMIT_SPEED = 0XBC,//Current speed limit value, with the lower 8 bits for current speed limit	value and higher 8 bits for the full range value, unit: 0.1km/h
	NB_QUK_SYS_POWER = 0XBD,// Scooter Power, unit: W
	BAT_CAPACITY = 0X18,//Design capacity of the battery, mAh
	BAT_TOTAL_CAPACITY = 0X19,//Full charge capacity of the battery,mAh
	BAT_DESIGN_VOLTAGE = 0X1A,//Design voltage of the battery, 10mV
	BAT_CYCLE_TIMES = 0X1B,//Cycle times of the battery
	BAT_CHARGE_TIMES = 0X1C,//Battery charging times
	BAT_CHARGE_CAP_L = 0X1D,//Lower 16 bits of the accumulative charge capacity of the battery,10mAh
	BAT_CHARGE_CAP_H = 0X1E,//Higher 16 bits of the accumulative charge capacity of the battery,10mAh
	BAT_OVER_DISCHARGE_TIMES = 0x1f,//Battery overflowing and over-discharging times, with the lower 8bits indicating the overflowing times and higher 8 bits indicating over-discharging times
	BAT_FUN_BOOLEAN = 0x30, //Boolean variable
	BAT_REMAINING_CAP = 0x31,//Current residual capacity, mAh
	BAT_REMAINING_CAP_PERCENT = 0x32,//Current residual capacity percentage,0-100
	BAT_CURRENT_CUR = 0x33, //Current current, 10mA
	BAT_VOLTAGE_CUR = 0x34, //Current voltage, 10mV
	BAT_TEMP_CUR = 0x35, //Temperature, with the higher 8 bits and lower 8 bits indicating temperatures of two temperature sensors respectively, 0-119 corresponding to -20 - 99
	BAT_BALANCE_STATU = 0x36 , //Balanced open status of the protective plate
	BAT_ODIS_STATE = 0x37 , // Unde-rvoltage condition of battery cell
	BAT_OCHG_STATE = 0x38 , // Over-voltage condition of battery cell
	BAT_CAP_COULO = 0x39 , // Coulomb-meter capacity
	BAT_CAP_VOL = 0x3a , //Volt-meter capacity
	BAT_HEALTHY = 0x3b , // Health degree
	BAT_CORE_VOLT_1 = 0x40, //Single cell voltage (N.1)
	BAT_CORE_VOLT_2 = 0x41, //Single cell voltage (N.2)
	BAT_CORE_VOLT_3 = 0x42, //Single cell voltage (N.3)
	BAT_CORE_VOLT_4 = 0x43, //Single cell voltage (N.4)
	BAT_CORE_VOLT_5 = 0x44, //Single cell voltage (N.5)
	BAT_CORE_VOLT_6 = 0x45, //Single cell voltage (N.6)
	BAT_CORE_VOLT_7 = 0x46, //Single cell voltage (N.7)
	BAT_CORE_VOLT_8 = 0x47, //Single cell voltage (N.8)
	BAT_CORE_VOLT_9 = 0x48, //Single cell voltage (N.9)
	BAT_CORE_VOLT_10 = 0x49, //Single cell voltage (N.10)
}mas_control_memory_reg;

/*************************/

/*Private Variables */

uint8_t MasterControlMessage[11] = 	 {header1,header2,0x02, Mobile_ID,ESC_ID,	  0	   ,	 0x1B		 ,0x02	  ,0x00     ,0		  ,0};
MaxG30_Master_Control_Registers EscooterRegs;
BufStat BufferStatus = empty;
device_type device = DRV;
int i=0,k=0,k1=0;
/*************************/

/*Private Functions Definitions*/

void WriteParam (mas_control_memory_reg RegAdd , uint16_t value);
void WriteCustomParam (mas_control_memory_reg RegAdd , uint16_t value);


/*************************/

/***************************public functions declarations***********************/
uint16_t GetErrorCode(){
	return EscooterRegs.CNB_INF_ERROR_REG;
}

uint16_t GetState(){
	return EscooterRegs.NB_INF_BOOL_REG;
}

uint16_t GetBatPerce(){
	return EscooterRegs.NB_INF_BTC_REG;
}

uint16_t GetActualMil(){
	return EscooterRegs.NB_INF_ACTUAL_MIL_REG;
}

uint16_t GetPrdMil(){
	return EscooterRegs.NB_INF_PRD_RID_MIL_REG;
}

float GetCurSpeed (){
	return EscooterRegs.NB_INF_SPEED_REG/10.0;
}

uint16_t GetRidMil(){
	return EscooterRegs.NB_INF_RID_MIL_SIG_REG;
}

uint16_t GetRunTim(){
	return EscooterRegs.NB_INF_RUN_TIM_SIG_REG;
}

uint16_t GetRidTim(){
	return EscooterRegs.NB_INF_RID_TIM_SIG_REG;
}

uint32_t GetTotalRidMil(){
	return ((uint32_t)(EscooterRegs.NB_INF_RID_MIL_L_REG)|(uint32_t)(EscooterRegs.NB_INF_RID_MIL_H_REG<<16));
}

uint32_t GetTotalRunTim(){
	return ((uint32_t)(EscooterRegs.NB_INF_RUN_TIM_L_REG)|(uint32_t)(EscooterRegs.NB_INF_RUN_TIM_H_REG<<16));
}

uint32_t GetTotalRidTim(){
	return ((uint32_t)(EscooterRegs.NB_INF_RID_TIM_L_REG)|(uint32_t)(EscooterRegs.NB_INF_RID_TIM_H_REG<<16));
}

float GetScooterTemp (){
	return EscooterRegs.NB_INF_BODY_TEMP_REG/10.0;
}

float GetMosTemp(){
	return EscooterRegs.NB_INF_MOS_TEMP_REG/10.0;
}

float GetDriverVolt(){
	return EscooterRegs.NB_INF_DRV_VOLT_REG/100.0;
}

float GetMotorCurrrent(){
	return EscooterRegs.NB_INF_MOT11_CURT_P_REG/100.0;
}

float GetAvrSpeed (){
	return EscooterRegs.NB_INF_AVRSPEED_REG/10.0;
}

uint16_t GetLockStatus(){
if((EscooterRegs.NB_INF_BOOL_REG&2)==2)
	return 1;
else return 0;
}

WRKMOD GetWorkMode(){
	switch(EscooterRegs.NB_CTL_WORKMODE_REG){
	case 0 : return NORMAL;
	case 1 : return ECO;
	case 2 : return SPORT;
	default : return NONE;
	}
	}
uint8_t GetNormalSpeed(){
	return (uint8_t)EscooterRegs.NB_CTL_NOMALSPEED_REG;
}
uint8_t GetLimitSpeed(){
	return (uint8_t)EscooterRegs.NB_CTL_LIMIT_SPD_REG;
}
uint8_t GetLiteSpeed(){
	return (uint8_t)EscooterRegs.NB_CTL_LITSPEED_REG;
}
float GetFullSpeed (){
	return ((uint8_t)(EscooterRegs.NB_QUK_CRT_LIMIT_SPEED_REG>>8)/10.0);
}

uint16_t GetScooterPower(){
	return EscooterRegs.NB_QUK_SYS_POWER_REG;
}

uint16_t GetBatCapcity(){
	return EscooterRegs.BAT_CAPACITY_REG;
}

uint16_t GetBatTotalCapcity(){
	return EscooterRegs.BAT_TOTAL_CAPACITY_REG;
}

float GetBatDesignVoltage(){
	return EscooterRegs.BAT_DESIGN_VOLTAGE_REG/100.0;
}

uint16_t GetBatCycleTimes(){
	return EscooterRegs.BAT_CYCLE_TIMES_REG;
}

uint16_t GetBatChargeTimes(){
	return EscooterRegs.BAT_CHARGE_TIMES_REG;
}

uint32_t GetBatChargeCap(){
	return ((uint32_t)(EscooterRegs.BAT_CHARGE_CAP_L_REG)|(uint32_t)(EscooterRegs.BAT_CHARGE_CAP_H_REG<<16))*10;
}

uint8_t GetBatOverDisChargeTimes(){
	return (uint8_t)(EscooterRegs.BAT_OVER_DISCHARGE_TIMES_REG);
}

uint8_t GetBatOverFlowingTimes(){
	return (uint8_t)(EscooterRegs.BAT_OVER_DISCHARGE_TIMES_REG>>8);
}

uint16_t GetBatRemainCap(){
	return EscooterRegs.BAT_REMAINING_CAP_REG;//BAT_FUN_BOOLEAN_REG
}

uint16_t GetBatRemainCapPerc(){
	return EscooterRegs.BAT_REMAINING_CAP_PERCENT_REG;
}

float GetBatCurrent(){
	return EscooterRegs.BAT_CURRENT_CUR_REG/100.0;
}

int16_t GetBatCurrent_mA(){
	return EscooterRegs.BAT_CURRENT_CUR_REG*10;
}

float GetBatVoltage(){
	return EscooterRegs.BAT_VOLTAGE_CUR_REG/100.0;
}

float GetBatTemp_S1(){
	return ((uint8_t)EscooterRegs.BAT_TEMP_CUR_REG)-20.0;
}

float GetBatTemp_S2(){
	return ((uint8_t)(EscooterRegs.BAT_TEMP_CUR_REG>>8))-20.0;
}

uint16_t GetBatCapCulo(){
	return EscooterRegs.BAT_CAP_COULO_REG;
}

uint16_t GetBatCapVol(){
	return EscooterRegs.BAT_CAP_VOL_REG;
}

uint16_t GetBatHealthy(){
	return EscooterRegs.BAT_HEALTHY_REG;
}

float GetBatCoreVolt_1(){
	return EscooterRegs.BAT_CORE_VOLT_1_REG/1000.0;
}

float GetBatCoreVolt_2(){
	return EscooterRegs.BAT_CORE_VOLT_2_REG/1000.0;
}

float GetBatCoreVolt_3(){
	return EscooterRegs.BAT_CORE_VOLT_3_REG/1000.0;
}

float GetBatCoreVolt_4(){
	return EscooterRegs.BAT_CORE_VOLT_4_REG/1000.0;
}

float GetBatCoreVolt_5(){
	return EscooterRegs.BAT_CORE_VOLT_5_REG/1000.0;
}

float GetBatCoreVolt_6(){
	return EscooterRegs.BAT_CORE_VOLT_6_REG/1000.0;
}

float GetBatCoreVolt_7(){
	return EscooterRegs.BAT_CORE_VOLT_7_REG/1000.0;
}

float GetBatCoreVolt_8(){
	return EscooterRegs.BAT_CORE_VOLT_8_REG/1000.0;
}

float GetBatCoreVolt_9(){
	return EscooterRegs.BAT_CORE_VOLT_9_REG/1000.0;
}

float GetBatCoreVolt_10(){
	return EscooterRegs.BAT_CORE_VOLT_10_REG/1000.0;
}

//*****************Commands*********************/

void Lock(){
	WriteParam(NB_CTL_LOCK,1);
}

void Unlock(){
	WriteParam(NB_CTL_UNLOCK,1);
}

void Reboot(){
	WriteParam(NB_CTL_REBOOT,1);
	EscooterRegs = (MaxG30_Master_Control_Registers) {0};
}
void Shutdown(){
	WriteParam(NB_CTL_POWEROFF,1);
}
void SetSpeedLimit(uint8_t speed,SPDTyp type){// 0.1(Kmeter/h)
//	WriteParam(NB_CTL_ENGINE,0);

	switch(type){
	case normal : WriteParam(NB_CTL_NOMALSPEED,speed);break;//WriteParam(NB_CTL_NOMALSPEED,speed*10);break;
	case LITE :  WriteParam(NB_CTL_LITSPEED,speed);break;
	case LIMIT :  WriteParam(NB_CTL_LIMIT_SPD,speed);break;
	}
	WriteParam(NB_CTL_REBOOT,1);
//	WriteParam(NB_CTL_ENGINE,1);
}
void ChangeCap(uint16_t newcap){
	WriteCustomParam(k1,newcap);k1++;//22 BATERY ID
}
void ChangeWorkMode(WRKMOD mode){
	WriteParam(NB_CTL_ENGINE,0);
	WriteParam(NB_CTL_WORKMODE,mode);
	WriteParam(NB_CTL_REBOOT,1);
	WriteParam(NB_CTL_ENGINE,1);
}

void ReleaseSpeed(){
//	WriteParam(NB_CTL_ENGINE,0);
	WriteParam(NB_CTL_LIMIT_SPD,250);
	WriteParam(NB_CTL_REBOOT,1);
//	WriteParam(NB_CTL_ENGINE,1);
}
void LimitSpeed(){
//	WriteParam(NB_CTL_ENGINE,0);
	WriteParam(NB_CTL_LIMIT_SPD,60);
	WriteParam(NB_CTL_REBOOT,1);
//	WriteParam(NB_CTL_ENGINE,1);
}
/********************************************************************************/

void RequestParam(){

	if (device==DRV){
		MasterControlMessage[datInd] = CNB_INF_ERROR;
		MasterControlMessage[DatSeg1]=0xb6;
		MasterControlMessage[targetID]=ESC_ID;
	}
	else if (device==BMS){
		MasterControlMessage[datInd] = BAT_CAPACITY;
		MasterControlMessage[DatSeg1]=0x6e;
		MasterControlMessage[targetID]=Battey_ID;
		}
	else if (device==NB_QUK){
		MasterControlMessage[datInd] = 0xb0;
		MasterControlMessage[DatSeg1]=0x20;
		MasterControlMessage[targetID]=ESC_ID;
	}
	MasterControlMessage[cmdWord]=CMD_CMAP_RD;
//	MasterControlMessage[DatSeg1]=0x02;
	MasterControlMessage[DatSeg2]=0x00;
	MasterControlMessage[frameheader1]= header1;
	addCRC(MasterControlMessage, 11);
	SendFullDublexMessage(MasterControlMessage, 11);}

void RequestCustomParam(){

	MasterControlMessage_CS[cmdWord]=CMD_CMAP_RD;
	MasterControlMessage_CS[DatSeg1]=0xb4;	//0x6e;battery registers
	MasterControlMessage_CS[datInd] = 0x1b;
	MasterControlMessage_CS[DatSeg2]=0x00;
	MasterControlMessage_CS[frameheader1]= header1;
	MasterControlMessage_CS[targetID]= ESC_ID;
	addCRC(MasterControlMessage_CS, 11);
	SendFullDublexMessage(MasterControlMessage_CS, 11);}

void WriteCustomParam (mas_control_memory_reg RegAdd , uint16_t value){
	MasterControlMessage_WRCS[frameheader1]= header1;
	MasterControlMessage_WRCS[targetID]=Battey_ID;
	MasterControlMessage_WRCS[cmdWord]=CMD_CMAP_WR_NR;
	MasterControlMessage_WRCS[datInd]= 0;
	MasterControlMessage_WRCS[packLen]=158;
	for(i=7;i<166;i+=2){
	MasterControlMessage_WRCS[i]=(uint8_t)value;
	MasterControlMessage_WRCS[i+1]=(uint8_t)(value>>8);
	}
	addCRC(MasterControlMessage_WRCS, 167);
	SendFullDublexMessage(MasterControlMessage_WRCS, 167);
}

void WriteParam (mas_control_memory_reg RegAdd , uint16_t value){
//	uint8_t P_read;
	MasterControlMessage_WR[frameheader1]= header1;
	MasterControlMessage_WR[targetID]=ESC_ID;
	MasterControlMessage_WR[cmdWord]=CMD_CMAP_WR_NR;
//	P_read = MasterControlMessage[datInd];
	MasterControlMessage_WR[datInd]= RegAdd;
	MasterControlMessage_WR[DatSeg1]=(uint8_t)value;
	MasterControlMessage_WR[DatSeg2]=(uint8_t)(value>>8);
	addCRC(MasterControlMessage_WR, 11);
	SendFullDublexMessage(MasterControlMessage_WR, 11);
//	 MasterControlMessage[datInd] = P_read;
}

BufStat ReadParam1 () {//BufStat

	uint8_t DatSeg1 = 7;
	uint8_t DatSeg2 = 8;
	if(MCTL_Buffer[sourceID]==ESC_ID){

		if(MCTL_Buffer[datInd]==CNB_INF_ERROR){

			EscooterRegs.CNB_INF_ERROR_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_BOOL - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_BOOL_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_WORKMODE - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_WORKMODE_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_BTC - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_BTC_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_ACTUAL_MIL - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_ACTUAL_MIL_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_PRD_RID_MIL - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_PRD_RID_MIL_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_SPEED - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_SPEED_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_RID_MIL_L - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_RID_MIL_L_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_RID_MIL_H - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_RID_MIL_H_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_RID_MIL_SIG - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_RID_MIL_SIG_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_RUN_TIM_L - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_RUN_TIM_L_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_RUN_TIM_H - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_RUN_TIM_H_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_RID_TIM_L - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_RID_TIM_L_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_RID_TIM_H - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_RID_TIM_H_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_RUN_TIM_SIG - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_RUN_TIM_SIG_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_RID_TIM_SIG - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_RID_TIM_SIG_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_BODY_TEMP - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_BODY_TEMP_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_BAT1_TEMP - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_BAT1_TEMP_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_BAT2_TEMP - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_BAT2_TEMP_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_MOS_TEMP - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_MOS_TEMP_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_DRV_VOLT - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_DRV_VOLT_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_MOT11_CURT_P - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_MOT11_CURT_P_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_INF_AVRSPEED - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_INF_AVRSPEED_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_CTL_NOMALSPEED - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_CTL_NOMALSPEED_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_CTL_LITSPEED - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_CTL_LITSPEED_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_CTL_WORKMODE - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_CTL_WORKMODE_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_CTL_LIMIT_SPD - CNB_INF_ERROR;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_CTL_LIMIT_SPD_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);
		}

		else if (MCTL_Buffer[datInd]==0xb0){

			k = NB_QUK_CRT_LIMIT_SPEED - 0xb0;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_QUK_CRT_LIMIT_SPEED_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = NB_QUK_SYS_POWER - 0xb0;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.NB_QUK_SYS_POWER_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);
		}
	}

	else if(MCTL_Buffer[sourceID]==Battey_ID)
		{
			EscooterRegs.BAT_CAPACITY_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_TOTAL_CAPACITY - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_TOTAL_CAPACITY_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_DESIGN_VOLTAGE - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_DESIGN_VOLTAGE_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CYCLE_TIMES - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CYCLE_TIMES_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CHARGE_TIMES - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CHARGE_TIMES_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CHARGE_CAP_L - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CHARGE_CAP_L_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CHARGE_CAP_H - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CHARGE_CAP_H_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_OVER_DISCHARGE_TIMES - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_OVER_DISCHARGE_TIMES_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_FUN_BOOLEAN - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_FUN_BOOLEAN_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_REMAINING_CAP - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_REMAINING_CAP_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_REMAINING_CAP_PERCENT - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_REMAINING_CAP_PERCENT_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CURRENT_CUR - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CURRENT_CUR_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_VOLTAGE_CUR - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_VOLTAGE_CUR_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_TEMP_CUR - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_TEMP_CUR_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_BALANCE_STATU - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_BALANCE_STATU_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_ODIS_STATE - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_OCHG_STATE_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_OCHG_STATE - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_OCHG_STATE_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CAP_COULO - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CAP_COULO_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CAP_VOL - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CAP_VOL_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_HEALTHY - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_HEALTHY_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CORE_VOLT_1 - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CORE_VOLT_1_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CORE_VOLT_2 - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CORE_VOLT_2_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CORE_VOLT_3 - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CORE_VOLT_3_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CORE_VOLT_4 - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CORE_VOLT_4_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CORE_VOLT_5 - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CORE_VOLT_5_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CORE_VOLT_6 - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CORE_VOLT_6_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CORE_VOLT_7 - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CORE_VOLT_7_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CORE_VOLT_8 - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CORE_VOLT_8_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CORE_VOLT_9 - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CORE_VOLT_9_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

			k = BAT_CORE_VOLT_10 - BAT_CAPACITY;
			k*=2;
			DatSeg1 = 7+k;DatSeg2 = 8+k;
			EscooterRegs.BAT_CORE_VOLT_10_REG = MCTL_Buffer[DatSeg1]|(MCTL_Buffer[DatSeg2]<<8);

				}

	if (MCTL_Buffer[frameheader1]==header1)BufferStatus = ok;
	else BufferStatus = error;

	return BufferStatus;
}

GPS_ApplicationLayer.c

C/C++
/*
 * GPS_ApplicationLayer.c
 *
 *  Created on: Aug 1, 2023
 *      Author: Ibrahim
 */

#include "GPS_ApplicationLayer.h"
#include "MaxG30_DashBoard.h"
#include "MaxG30_Master control.h"
#include "stm32g0xx.h"
#include <string.h>
#include <stdlib.h>

extern UART_HandleTypeDef huart4; //IMU connection
extern UART_HandleTypeDef huart2; //Mosfet1 connection
extern UART_HandleTypeDef huart1; // Mian_Controller Connection

extern TIM_HandleTypeDef htim14;//DashBoard run

#define IMU_UART &huart4
#define Mosfet1_UART &huart2
#define MCTL_UART &huart1

#define DashBoard_TIM &htim14

#define BleBuffer_N 220
#define IMU_Buffer_N 50
#define DRV_Buffer_N 189
#define NB_QUK_Buffer_N 39
#define BMS_Buffer_N 119

DashBoard_Status DashBoard_state=not_activated;
MaxG30_Master_Control_Attributes Escooter1;

uint8_t IMU_BufferCpy[50];
uint8_t IMU_Buffer[50];
uint8_t BLE_BUFFER[220];
uint8_t MCTL_Buffer[200];
uint32_t Tickstart1=0;
uint16_t ref,pre_ref;
uint8_t ESP_MSG;
uint8_t c1=0,c2=0;
float throttle_test;
uint8_t *ptr1;
uint8_t j;
extern uint8_t BrakeFlag;
uint8_t LightFlag=0;
SPDTyp speed_type=LIMIT;
extern device_type device;
extern BufStat BufferStatus;
uint16_t temp_RidMil;
uint16_t temp_RidTim;
uint16_t temp_RunTim;
uint16_t temp;

void UpdateAttr_Handler();
void Update_MCTRL_Attributes_STRCT (device_type target);//uint8_t attrN
void Update_BLE_BUFFER (uint8_t* value,char value_type , char start);
void Process_IMU_Buffer();
float GetXaxis();
float GetYaxis();

void GPS_Init(){
	HAL_UART_Receive_IT (IMU_UART, &ESP_MSG, 1);
	HAL_UART_Receive_DMA(Mosfet1_UART, IMU_Buffer, IMU_Buffer_N);
	HAL_TIM_Base_Start_IT(&htim14);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){

	if(htim==DashBoard_TIM){//every 10 mSec

		if(DashBoard_state==activated){
		if(c2==10) {
			device = DRV;
			HAL_UART_DMAStop(MCTL_UART);
			HAL_UART_Receive_DMA(MCTL_UART,MCTL_Buffer, DRV_Buffer_N);
			RequestParam();}

		if(c2==20) {
			if(BLE_BUFFER[0]==0)
			{c2=0;
			goto exit;
			}

			device = NB_QUK;
			HAL_UART_DMAStop(MCTL_UART);
			HAL_UART_Receive_DMA(MCTL_UART,MCTL_Buffer, NB_QUK_Buffer_N);
			RequestParam();}

		if(c2==30) {
			device = BMS;
			HAL_UART_DMAStop(MCTL_UART);
			HAL_UART_Receive_DMA(MCTL_UART,MCTL_Buffer, BMS_Buffer_N);
			RequestParam(); c2=0;}
		c2++;
		}
		exit :if(c2!=10&&c2!=20&&c2!=30)DashBoardRun();
	}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{

	if(huart==MCTL_UART){
		ReadParam1();
		Update_MCTRL_Attributes_STRCT(device);
	}

	if(huart==IMU_UART){
		HAL_UART_Receive_IT (IMU_UART, &ESP_MSG, 1);
		switch(ESP_MSG){//process the ESP message
		case 'a' ://controller is activated
			DashBoard_state=activated;break;//61
		case 'b' ://lock
			Lock();break;//62
		case 'c' ://unlock
			Unlock();break;//63
		case 'd' ://Reboot
			{Reboot();
			Escooter1 = (MaxG30_Master_Control_Attributes) {0};

			break;//64
			}
		case 'e' ://shutdown
			{Shutdown();DashBoard_state=not_activated;break;}//65
			
		case 'h' ://68 // turn on the front light
		{
			LightFlag=!LightFlag;
			HAL_UART_Transmit(Mosfet1_UART, &LightFlag, 1, 0xffff);break;
		}
		case 'E' :
			ChangeWorkMode(ECO);break;//45
		case 'S' :
			ChangeWorkMode(SPORT);break;//53
		case 'N' :
			ChangeWorkMode(NORMAL);break;//4e
		case 'R' :
			ReleaseSpeed();break;//52
		case 'L' :
			LimitSpeed();break;//4c
		case 'n' :
			speed_type=normal;break;//6e
		case 'm' :
			speed_type=LIMIT;break;//6d
		case 'i' :
			speed_type=LITE;break;//69
		case 'C' :
			RequestCustomParam();break;//43
		default :
			if(ESP_MSG<22)SetSpeedLimit(ESP_MSG,speed_type);

	}
	}
}

void Update_MCTRL_Attributes_STRCT (device_type target)
	{
	if(target == DRV){

			Escooter1.ErrorCode=GetErrorCode();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.ErrorCode,'U','a');

			Escooter1.State=GetState();
			Escooter1.WorkMode=GetWorkMode();
			Escooter1.NormalSpeed=GetNormalSpeed();
			Escooter1.LiteSpeed=GetLiteSpeed();
			Escooter1.LimitSpeed=GetLimitSpeed();

			Escooter1.BatPerce=GetBatPerce();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatPerce,'U','b');

			Escooter1.ActualMil=GetActualMil();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.ActualMil,'U','c');

			Escooter1.PrdMil=GetPrdMil();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.PrdMil,'U','d');

			Escooter1.CurrSpeed=GetCurSpeed();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.CurrSpeed,'F','e');

			Escooter1.TotalRidMil=GetTotalRidMil();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.TotalRidMil,'L','f');

			Escooter1.TotalRunTim=GetTotalRunTim();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.TotalRunTim,'L','g');

			Escooter1.TotalRidTim=GetTotalRidTim();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.TotalRidTim,'L','h');

			Escooter1.BodyTemp=GetScooterTemp();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BodyTemp,'F','i');

			Escooter1.MosTemp=GetMosTemp();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.MosTemp,'F','j');

			Escooter1.DriverVolt=GetDriverVolt();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.DriverVolt,'F','k');

			Escooter1.MotorCurrrent=GetMotorCurrrent();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.MotorCurrrent,'F','l');

			Escooter1.AvrSpeed=GetAvrSpeed();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.AvrSpeed,'F','m');

			Escooter1.LockState=GetLockStatus();
			Update_BLE_BUFFER(&Escooter1.LockState,'u','n');

			Escooter1.SpeedLimit=(float)GetLimitSpeed();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.SpeedLimit,'F', 'o');

			temp = GetRidMil();
			if(Escooter1.RidMil>temp){//there is previous value
				if(temp_RidMil==0)
					{temp=temp_RidMil;//first time
					Escooter1.RidMil+= temp;
					}
				else 				//next times
					{Escooter1.RidMil+= temp - temp_RidMil; //add the difference
					temp_RidMil=temp;//save the current value
					}
			}
			else Escooter1.RidMil=temp;
//			Update_BLE_BUFFER((uint8_t*)&Escooter1.RidMil,'U','r');

			Escooter1.roll=GetXaxis();
//			Update_BLE_BUFFER((uint8_t*)&Escooter1.roll,'F', 's');

			Escooter1.pitch=GetYaxis();
//			Update_BLE_BUFFER((uint8_t*)&Escooter1.pitch,'F', 't');

			temp = GetRidTim();
			if(Escooter1.RidTim>temp){//there is previous value
				if(temp_RidTim==0)
					{temp=temp_RidTim;//first time
					Escooter1.RidTim+= temp;
					}
				else 				//next times
					{Escooter1.RidTim+= temp - temp_RidTim; //add the difference
					temp_RidTim=temp;//save the current value
					}
			}
			else Escooter1.RidTim=temp;
//			Update_BLE_BUFFER((uint8_t*)&Escooter1.RidTim,'U','u');

			temp = GetRunTim();
			if(Escooter1.RunTim>temp){//there is previous value
				if(temp_RunTim==0)
					{temp=temp_RunTim;//first time
					Escooter1.RunTim+= temp;
					}
				else 				//next times
					{Escooter1.RunTim+= temp - temp_RunTim; //add the difference
					temp_RunTim=temp;//save the current value
					}
			}
			else Escooter1.RunTim=temp;
//			Update_BLE_BUFFER((uint8_t*)&Escooter1.RunTim,'U','v');
		}

	else if (target == NB_QUK){

//			if(BLE_BUFFER[0]==0){
//				BLE_BUFFER[0]=1;
//			}

			Escooter1.FullSpeed=GetFullSpeed();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.FullSpeed,'F', 'p');

			Escooter1.ScooterPower=GetScooterPower();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.ScooterPower,'U', 'q');

			Update_BLE_BUFFER((uint8_t*)&Escooter1.RidMil,'U','r');
			Update_BLE_BUFFER((uint8_t*)&Escooter1.roll,'F', 's');
			Update_BLE_BUFFER((uint8_t*)&Escooter1.pitch,'F', 't');
			Update_BLE_BUFFER((uint8_t*)&Escooter1.RidTim,'U','u');
			Update_BLE_BUFFER((uint8_t*)&Escooter1.RunTim,'U','v');

	}

	else if(target == BMS){

			Escooter1.BatteryCapacity=GetBatCapcity();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatteryCapacity,'U', 'w');

			Escooter1.TotalBatteryCapacity=GetBatTotalCapcity();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.TotalBatteryCapacity,'U', 'x');

			Escooter1.BatDesignVoltage=GetBatDesignVoltage();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatDesignVoltage,'F', 'y');

			Escooter1.BatCycleTimes=GetBatCycleTimes();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCycleTimes,'U', 'z');

			Escooter1.BatChargeTimes=GetBatChargeTimes();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatChargeTimes,'U', 'A');

			Escooter1.BatChargeCap=GetBatChargeCap();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatChargeCap,'L', 'B');

			Escooter1.BatOverDisChargeTimes=GetBatOverDisChargeTimes();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatOverDisChargeTimes,'u', 'C');

			Escooter1.BatOverFlowingTimes=GetBatOverFlowingTimes();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatOverFlowingTimes,'u', 'D');

			Escooter1.BatRemainCap=GetBatRemainCap();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatRemainCap,'U', 'E');

			Escooter1.BatRemainCapPerc=GetBatRemainCapPerc();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatRemainCapPerc,'U', 'F');

			Escooter1.BatCurrent=GetBatCurrent();

			if(Escooter1.BatCurrent<0){
				Escooter1.BatVoltage=0;
			}

			if(Tickstart1==0){
				Escooter1.BatCalcDraiCAP= (GetBatCurrent_mA()*HAL_GetTick())/3600000.0;
				Tickstart1 = HAL_GetTick();
			}
			else {
				Escooter1.BatCalcDraiCAP+=((float)GetBatCurrent_mA()*(float)(HAL_GetTick() - Tickstart1))/3600000.0;
				Tickstart1=HAL_GetTick();
			}

			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCurrent,'F', 'G');

			Escooter1.BatVoltage=GetBatVoltage();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatVoltage,'F', 'H');

			Escooter1.BatTemp_S1=GetBatTemp_S1();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatTemp_S1,'F', 'I');

			Escooter1.BatTemp_S2=GetBatTemp_S2();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatTemp_S2,'F', 'J');

			Escooter1.BatCapCulo=GetBatCapCulo();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCapCulo,'U', 'K');

			Escooter1.BatCapVol=GetBatCapVol();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCapVol,'U', 'L');

			Escooter1.BatHealthy=GetBatHealthy();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatHealthy,'U', 'M');

			Escooter1.BatCoreVolt1=GetBatCoreVolt_1();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCoreVolt1,'F', 'N');

			Escooter1.BatCoreVolt2=GetBatCoreVolt_2();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCoreVolt2,'F', 'O');

			Escooter1.BatCoreVolt3=GetBatCoreVolt_3();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCoreVolt3,'F', 'P');

			Escooter1.BatCoreVolt4=GetBatCoreVolt_4();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCoreVolt4,'F', 'Q');

			Escooter1.BatCoreVolt5=GetBatCoreVolt_5();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCoreVolt5,'F', 'R');

			Escooter1.BatCoreVolt6=GetBatCoreVolt_6();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCoreVolt6,'F', 'S');

			Escooter1.BatCoreVolt7=GetBatCoreVolt_7();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCoreVolt7,'F', 'T');

			Escooter1.BatCoreVolt8=GetBatCoreVolt_8();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCoreVolt8,'F', 'U');

			Escooter1.BatCoreVolt9=GetBatCoreVolt_9();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCoreVolt9,'F', 'V');

			Escooter1.BatCoreVolt10=GetBatCoreVolt_10();
			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCoreVolt10,'F', 'W');

			Update_BLE_BUFFER((uint8_t*)&BrakeFlag,'u', 'X');

			Update_BLE_BUFFER((uint8_t*)&Escooter1.WorkMode,'u', 'Y');

			Update_BLE_BUFFER((uint8_t*)&Escooter1.BatCalcDraiCAP,'F', 'Z');

			Update_BLE_BUFFER((uint8_t*)&LightFlag,'u', 91);

			HAL_UART_Transmit(IMU_UART, BLE_BUFFER, BleBuffer_N, 0xffff);

			memset(BLE_BUFFER,0,220);
			DashBoard_state=not_activated;

//			pre_ref=ref;
			ref=0;
		}
	}

void Update_BLE_BUFFER (uint8_t* ptr,char value_type , char start){

	switch(value_type){

	case 'u':{//uint8_t
		BLE_BUFFER[ref]=(uint8_t)start;ref++;
		BLE_BUFFER[ref]=*ptr;ref++;
			}break;

	case 'U':{//uint16_t
		BLE_BUFFER[ref]=(uint8_t)start;ref++;
		BLE_BUFFER[ref]=*ptr;ptr++;ref++;
		BLE_BUFFER[ref]=*ptr;ref++;
			}break;

	case 'F'://float
	case 'L'://uint32_t
	{
		BLE_BUFFER[ref]=(uint8_t)start;ref++;
		BLE_BUFFER[ref]=*ptr;ptr++;ref++;
		BLE_BUFFER[ref]=*ptr;ptr++;ref++;
		BLE_BUFFER[ref]=*ptr;ptr++;ref++;
		BLE_BUFFER[ref]=*ptr;ref++;
			}break;
	}
}

float GetXaxis(){

	float roll=0;

	for(j=0;j<(IMU_Buffer_N);j++)
	{
		IMU_BufferCpy[j]=IMU_Buffer[j];
	}

	//search for roll value
	for(j=0;j<(IMU_Buffer_N-5);j++)
	{
		if(IMU_BufferCpy[j]=='x'&&IMU_BufferCpy[j+5]=='y'){
			ptr1 = (uint8_t*)&roll;
			*ptr1=IMU_BufferCpy[j+1];ptr1++;
			*ptr1=IMU_BufferCpy[j+2];ptr1++;
			*ptr1=IMU_BufferCpy[j+3];ptr1++;
			*ptr1=IMU_BufferCpy[j+4];
			break;
		}
	}
	return roll;
}

float GetYaxis(){

	float pitch=0;

	for(j=0;j<(IMU_Buffer_N);j++)
	{
		IMU_BufferCpy[j]=IMU_Buffer[j];
	}

	//search for roll value
	for(j=0;j<(IMU_Buffer_N-5);j++)
	{
		if(IMU_BufferCpy[j]=='y'&&IMU_BufferCpy[j+5]=='t'){
			ptr1 = (uint8_t*)&pitch;
			*ptr1=IMU_BufferCpy[j+1];ptr1++;
			*ptr1=IMU_BufferCpy[j+2];ptr1++;
			*ptr1=IMU_BufferCpy[j+3];ptr1++;
			*ptr1=IMU_BufferCpy[j+4];
			break;
		}
	}
	return pitch;
}

ESP32_ApplicationLayer.c

C/C++
/*
 * ESP32_ApplicationLayer.c
 *
 *  Created on: Aug 2, 2023
 *      Author: Ibrahim
 */

#include "ESP32_ApplicationLayer.h"
#include "stm32g0xx.h"
#include <string.h>

extern UART_HandleTypeDef huart6;// IMU connection
extern UART_HandleTypeDef huart3;//ESP connection
extern UART_HandleTypeDef huart2;//Mosfet2 connection

extern TIM_HandleTypeDef htim14;


#define IMU_UART &huart6
#define ESP_UART &huart3
#define Mosfet2_UART &huart2

#define DashBoard_Pin GPIO_PIN_9
#define DashBoard_GPIO_Port GPIOA
#define Driver_Trigger_Pin GPIO_PIN_10
#define Driver_Trigger_GPIO_Port GPIOA

#define BleBuffer_N 220
#define IMU_Buffer_N 21

typedef enum{
	ok = 0,
	error = 1,
	empty = 2,
	available = 3,
}BufStat;

void Process_BleBuffer();
void Process_ESP_MSG();


uint8_t IMU_Buffer[21];
uint8_t ESP_MSG;
uint8_t Mosfet2_MSG;
uint8_t BleBuffer[220];
uint8_t ActivateFlag=1;
BufStat BufferStatus = empty;
uint8_t i,c,c1;

void ESP32_Init(){

	HAL_UART_Receive_DMA(ESP_UART, &ESP_MSG, 1);
	HAL_UART_Receive_DMA(IMU_UART, BleBuffer, BleBuffer_N);
	HAL_TIM_Base_Start_IT(&htim14);
}



void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){

	//call every 0.01 Sec

	if (ActivateFlag){ //if shut down do no thing

	//every 100 counts check if the driver is active
	if(c1==100){

	if(!HAL_GPIO_ReadPin(DashBoard_GPIO_Port, DashBoard_Pin))

		{HAL_GPIO_WritePin(Driver_Trigger_GPIO_Port, Driver_Trigger_Pin, GPIO_PIN_SET );}

	else

		{HAL_GPIO_WritePin(Driver_Trigger_GPIO_Port, Driver_Trigger_Pin, GPIO_PIN_RESET );}
	c1=0;
	}
	c1++;

	//check if there is available data to send and remind the gps module that the driver is ready
	if(BufferStatus == empty)
	{
//	c++;
//	if(c==20){
	ESP_MSG = (uint8_t)'a';
	HAL_UART_Transmit(IMU_UART, &ESP_MSG, 1, 0xffff);//}
	}
	else if (BufferStatus == available)
	{ // send the buffer to the mobile app every 50 counts as parts with space between them 1 counts
//		if (c==50){//&&BleBuffer[3]=='b'
		HAL_UART_Transmit(ESP_UART, &BleBuffer[i], 20, 0xffff);
//		if(i==0)BleBuffer[0]=0;//to recognize the new buffer when it come

		//search for the brake flag
		if(i>200)
		for(int j=0;j<i;j++)
		{
			if(BleBuffer[j]=='X'&&BleBuffer[j+2]=='Y'){
				HAL_UART_Transmit(Mosfet2_UART, &BleBuffer[j+1],1, 0xffff);
				break;
			}
		}

		i+=20;
		if(i>200){i=0;BufferStatus = empty;memset(BleBuffer,0,220);}
	}
	}
//	if(c<50)c++;
	else {c=0;c1=0;BleBuffer[0]=0;}//if shut down reset counters
}


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){

	if(huart==IMU_UART){
		BufferStatus = available;
	}

	if(huart==ESP_UART){

	HAL_UART_Receive_IT (ESP_UART, &ESP_MSG, 1);

	switch(ESP_MSG){//process the ESP message
//	case 'a' : // Reserved (the driver is alive message esp to gps )
	//transmit the order
	case 'b' : // lock
	case 'c' : // unlock
	case 'd' : //Reboot
	case 'e' : // shutdown
	default :	//speed limit
		HAL_UART_Transmit(IMU_UART, &ESP_MSG, 1, 0xffff);break;
	}
	switch(ESP_MSG){
//	case 'd':
	case 'e':ActivateFlag=0;break;
	case 'f':ActivateFlag=1;break;

	}
	}
}

Mosfet1_ApplicationLayer.c

C/C++
/*
 * Mosfet1_ApplicationLayer.c
 *
 *  Created on: Jul 31, 2023
 *      Author: Ibrahim
 */

#include "Mosfet1_ApplicationLayer.h"
#include "stm32g0xx.h"

extern UART_HandleTypeDef huart3;// IMU connection
extern UART_HandleTypeDef huart6;// GPS connection

#define IMU_UART &huart3
#define GPS_UART &huart6

#define IMU_Buffer_N 21


uint8_t IMU_Buffer[30];
uint8_t GPS_Message;

void Mosfet1Init(){
	HAL_UART_Receive_DMA(IMU_UART, IMU_Buffer, IMU_Buffer_N);
	HAL_UART_Receive_IT(GPS_UART, &GPS_Message, 1);
}


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart==IMU_UART){
    	HAL_UART_Transmit(GPS_UART, IMU_Buffer, IMU_Buffer_N, 0xffff);
    }
    if(huart==GPS_UART){
    	HAL_UART_Receive_IT(GPS_UART, &GPS_Message, 1);
    	if(GPS_Message)
    		HAL_GPIO_WritePin(Front_Light_GPIO_Port, Front_Light_Pin, SET);
    	else
    		HAL_GPIO_WritePin(Front_Light_GPIO_Port, Front_Light_Pin, RESET);
    }
}

Mosfet2_ApplicationLayer.c

C/C++
/*
 * Mosfet2_ApplicationLayer.c
 *
 *  Created on: Aug 6, 2023
 *      Author: Ibrahim
 */

#include "stm32g0xx.h"
#include "Mosfet2_ApplicationLayer.h"

uint8_t ESP_MSG;

extern UART_HandleTypeDef huart6; //ESP connection

#define ESP_UART &huart6

void Mosfet2_Init(){
	HAL_UART_Receive_IT (ESP_UART, &ESP_MSG, 1);
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart==ESP_UART){
	HAL_UART_Receive_IT (ESP_UART, &ESP_MSG, 1);

    if(ESP_MSG)
    	HAL_GPIO_WritePin(Front_Light_GPIO_Port, Front_Light_Pin, SET);
   	else
   		HAL_GPIO_WritePin(Front_Light_GPIO_Port, Front_Light_Pin, RESET);

	}

}

Credits

Ibrahim Zaeiter
2 projects • 12 followers
Electronic Systems Engineer
Mahmoud Mardnly
12 projects • 19 followers
Embedded System Engineer
Abd Alrhman Hammal
5 projects • 16 followers
firmware programmer
Mohammad Khallouf
1 project • 4 followers
Nazir Dan
1 project • 4 followers
ReemBrimo
1 project • 5 followers
Mouhamad Douba
0 projects • 6 followers

Comments