I have a project that need to read ADC value in 1.5K SPS,
and then use BLE transfer the data to my laptop.
I used "analogRead()" to read ADC value.
My BLE package size is 217 Byte that including 24 samples and 9 axis raw data
So the ideal BLE transfer speed should be 62.5 Hz or faster
But I found that the max transfer speed only 31.6 Hz
How can I modify and optimize my sketch, any advice is appreciated.
#include <ArduinoBLE.h>
#include <Arduino_LSM9DS1.h>
#define BLE_BUFFER_SIZES 217
#define BLE_DEVICE_NAME "My sensors"
#define BLE_LOCAL_NAME "My sensors"
BLEService BLESensors("f2361993-bcce-44d6-bf2b-29d801d662b5");
BLECharacteristic multiBLE("00000001-0000-1000-8000-00805f9b34fb", BLERead | BLENotify | BLEBroadcast, BLE_BUFFER_SIZES);
int EMG_pin[2] = {A0, A1};
int sensorValue[2] = {0, 0};
unsigned long previousTimes;
unsigned long currentMicroTimes = 0;
int preMicroTime = 0,proMicroTime = 0;
int Interval = 0;
int Timebuf = 0;
int Microtemp = 0;
unsigned long currentSensorMicroTimes = 0;
unsigned long previoussEMGTimes = 0;
int sEMGpacCount = 0;
int packageCount = 0;
byte previousIMUTimes[5] = {0x00,0x00,0x00,0x00,0x00};
int Hour = 0,Min = 0,Sec = 0,Msec = 0, Count = 0, EMGCount = 0;
float EMGSecTime = 0.0;
float SecTemp;
int sEMGildx = 48;
byte IMUheader[2] = {0x55,0xAA};
byte EMGheader[2] = {0xAA,0x55};
byte body[6] = {0x01,0x02,0x03,0x04,0x05,0x06};
int EMGcounter = 0;
int EMGtimecounter = 0;
float Acc[3], Gyro[3], Mag[3];
byte Signal[3];
byte AccXb[4] = {0x00,0x00,0x00,0x00};
byte AccYb[4] = {0x00,0x00,0x00,0x00};
byte AccZb[4] = {0x00,0x00,0x00,0x00};
byte GyroXb[4] = {0x00,0x00,0x00,0x00};
byte GyroYb[4] = {0x00,0x00,0x00,0x00};
byte GyroZb[4] = {0x00,0x00,0x00,0x00};
byte MagXb[4] = {0x00,0x00,0x00,0x00};
byte MagYb[4] = {0x00,0x00,0x00,0x00};
byte MagZb[4] = {0x00,0x00,0x00,0x00};
byte sEMG[72] = {0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00};
byte EMGtime[4] = {0x00,0x00,0x00,0x00};
byte multiSensorpacket[217] = {IMUheader[0],IMUheader[1],
previousIMUTimes[0],previousIMUTimes[1],previousIMUTimes[2],previousIMUTimes[3],previousIMUTimes[4],
body[0],
AccXb[0],AccXb[1],AccXb[2],AccXb[3],
AccYb[0],AccYb[1],AccYb[2],AccYb[3],
AccZb[0],AccZb[1],AccZb[2],AccZb[3],
GyroXb[0],GyroXb[1],GyroXb[2],GyroXb[3],
GyroYb[0],GyroYb[1],GyroYb[2],GyroYb[3],
GyroZb[0],GyroZb[1],GyroZb[2],GyroZb[3],
MagXb[0],MagXb[1],MagXb[2],MagXb[3],
MagYb[0],MagYb[1],MagYb[2],MagYb[3],
MagZb[0],MagZb[1],MagZb[2],MagZb[3],
(byte)Count,
EMGheader[0],EMGheader[1],
body[0],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
EMGtime[0],EMGtime[1],EMGtime[2],EMGtime[3],
sEMG[0],sEMG[1],sEMG[2],
sEMG[3],sEMG[4],sEMG[5],
sEMG[6],sEMG[7],sEMG[8],
sEMG[9],sEMG[10],sEMG[11],
sEMG[12],sEMG[13],sEMG[14],
sEMG[15],sEMG[16],sEMG[17],
sEMG[18],sEMG[19],sEMG[20],
sEMG[21],sEMG[22],sEMG[23],
sEMG[24],sEMG[25],sEMG[26],
sEMG[27],sEMG[28],sEMG[29],
sEMG[30],sEMG[31],sEMG[32],
sEMG[33],sEMG[34],sEMG[35],
sEMG[36],sEMG[37],sEMG[38],
sEMG[39],sEMG[40],sEMG[41],
sEMG[42],sEMG[43],sEMG[44],
sEMG[45],sEMG[46],sEMG[47],
sEMG[48],sEMG[49],sEMG[50],
sEMG[51],sEMG[52],sEMG[53],
sEMG[54],sEMG[55],sEMG[56],
sEMG[57],sEMG[58],sEMG[59],
sEMG[60],sEMG[61],sEMG[62],
sEMG[63],sEMG[64],sEMG[65],
sEMG[66],sEMG[67],sEMG[68],
sEMG[69],sEMG[70],sEMG[71],
(byte)EMGCount
};
byte *pointAccXb;
byte *pointAccYb;
byte *pointAccZb;
byte *pointGyroXb;
byte *pointGyroYb;
byte *pointGyroZb;
byte *pointMagXb;
byte *pointMagYb;
byte *pointMagZb;
byte *pointLTREMG;
byte *pointLTBEMG;
byte *pointEMGtime;
void setup()
{
Serial.begin(115200);
//while(!Serial);
if (!BLE.begin())
{
while (1);
}
else
{
BLE.setDeviceName(BLE_DEVICE_NAME);
BLE.setLocalName(BLE_LOCAL_NAME);
BLE.setAdvertisedService(BLESensors);
BLESensors.addCharacteristic(multiBLE);
BLE.addService(BLESensors);
BLE.advertise();
if (!IMU.begin())
{
Serial.println("Failed to initialize IMU!");
while (1);
}
IMU.setAccelFS(3);
IMU.setAccelODR(2);
IMU.setAccelOffset(0, 0, 0);
IMU.setAccelSlope (1, 1, 1);
IMU.setGyroFS(3);
IMU.setGyroODR(2);
IMU.setGyroOffset(0.327296, 2.791258, 3.269522);
IMU.setGyroSlope (1, 1, 1);
IMU.setMagnetFS(3);
IMU.setMagnetODR(6);
IMU.setMagnetOffset(0,0,0);
IMU.setMagnetSlope (1,1,1);
IMU.accelUnit = GRAVITY;
IMU.gyroUnit= DEGREEPERSECOND;
IMU.magnetUnit = MICROTESLA;
Serial.println("AccX, AccY, AccZ, GyX, GyY, GyZ, MagX, MagY, MagZ");
}
pinMode(LED_BUILTIN, OUTPUT);
}
void loop()
{
BLEDevice central = BLE.central();
if(central)
{
TimeReset();
bool dataGotFlag = false;
while(central.connected())
{
digitalWrite(LED_BUILTIN, HIGH);
reTime();
if(IMU.accelAvailable() && IMU.gyroAvailable())
{
IMU.readAccel(Acc[0], Acc[1], Acc[2]);
IMU.readGyro(Gyro[0], Gyro[1], Gyro[2]);
pointAccXb = (byte *)&Acc[0];
pointAccYb = (byte *)&Acc[1];
pointAccZb = (byte *)&Acc[2];
pointGyroXb = (byte *)&Gyro[0];
pointGyroYb = (byte *)&Gyro[1];
pointGyroZb = (byte *)&Gyro[2];
dataGotFlag = true;
}
if(IMU.magnetAvailable())
{
IMU.readMagnet(Mag[0], Mag[1], Mag[2]);
pointMagXb = (byte *)&Mag[0];
pointMagYb = (byte *)&Mag[1];
pointMagZb = (byte *)&Mag[2];
dataGotFlag = true;
}
if(dataGotFlag)
{
Serial.printf(
"%d,%.4f,%d,%d,%d,%d,%f,%f,%f,%f,%f,%f,%f,%f,%f\r\n",
Count,EMGSecTime, Hour ,Min ,Sec ,Msec,
Acc[0],
Acc[1],
Acc[2],
Gyro[0],
Gyro[1],
Gyro[2],
Mag[0],
Mag[1],
Mag[2]);
multiSensorpacket[2] = (byte)Hour;
multiSensorpacket[3] = (byte)Min;
multiSensorpacket[4] = (byte)Sec;
multiSensorpacket[5] = (byte)(Msec/256);
multiSensorpacket[6] = (byte)(Msec%256);
TurnToByte();
CountNum();
multiSensorpacket[44] = (byte)Count;
dataGotFlag = false;
}
previoussEMGTimes = currentSensorMicroTimes;
for(int j = 0; j < 24; j++)
{
ADCread();
}
multiBLE.writeValue(multiSensorpacket,217);
Serial.print(EMGSecTime);
Serial.print(",");
Serial.println(packageCount);
delayMicroseconds(15000);
EMGcounter = 0;
EMGtimecounter = 0;
sEMGpacCount = 0;
CountEMGNum();
multiSensorpacket[216] = (byte)EMGCount;
packageCount++;
}
}
digitalWrite(LED_BUILTIN, LOW);
}
}
void Intervalcal()
{
if(Timebuf != 0 && preMicroTime > Timebuf)
{
Interval = preMicroTime - Timebuf;
Microtemp = Microtemp + (Interval % 1000);
if(Microtemp < 1000 && Microtemp > 0)
{
Interval = Interval/1000;
}
else
{
Interval = Interval/1000 + Microtemp/1000;
Microtemp = Microtemp % 1000;
}
}
Timebuf = preMicroTime;
}
void Timer()
{
if(Msec + Interval < 1000)
{
Msec += Interval;
}
else if(Msec + Interval > 1000)
{
if(Sec < 59)
{
Sec += 1;
Msec = Msec + Interval - 1000;
}
else if(Sec == 59)
{
if(Min < 59)
{
Min += 1;
Sec = 0;
Msec = Msec + Interval - 1000;
}
else if(Min == 59)
{
Hour += 1;
Min = 0;
Msec = Msec + Interval - 1000;
}
}
}
}
void SecTimer()
{
EMGSecTime = Hour*3600 + Min*60 + Sec + (float(Msec)/1000) + (float(Microtemp)/1000000);
pointEMGtime = (byte *)&EMGSecTime;
for(int i = 3; i >= 0; i--)
{
EMGtime[i] = pointEMGtime[3-i];
}
}
void TimeReset()
{
Hour = 0;
Min = 0;
Sec = 0;
Msec = 0;
Interval = 0;
Microtemp = 0;
Timebuf = 0;
}
void CountNum()
{
if(Count < 255)
{
Count++;
}
else
{
Count = 0;
}
}
void CountEMGNum()
{
if(Count < 255)
{
EMGCount++;
}
else
{
EMGCount = 0;
}
}
void TurnToByte()
{
for(int i = 3; i >= 0; i--)
{
AccXb[i] = pointAccXb[3-i];
AccYb[i] = pointAccYb[3-i];
AccZb[i] = pointAccZb[3-i];
GyroXb[i] = pointGyroXb[3-i];
GyroYb[i] = pointGyroYb[3-i];
GyroZb[i] = pointGyroZb[3-i];
MagXb[i] = pointMagXb[3-i];
MagYb[i] = pointMagYb[3-i];
MagZb[i] = pointMagZb[3-i];
}
multiSensorpacket[8] = AccXb[0];
multiSensorpacket[9] = AccXb[1];
multiSensorpacket[10] = AccXb[2];
multiSensorpacket[11] = AccXb[3];
multiSensorpacket[12] = AccYb[0];
multiSensorpacket[13] = AccYb[1];
multiSensorpacket[14] = AccYb[2];
multiSensorpacket[15] = AccYb[3];
multiSensorpacket[16] = AccZb[0];
multiSensorpacket[17] = AccZb[1];
multiSensorpacket[18] = AccZb[2];
multiSensorpacket[19] = AccZb[3];
multiSensorpacket[20] = GyroXb[0];
multiSensorpacket[21] = GyroXb[1];
multiSensorpacket[22] = GyroXb[2];
multiSensorpacket[23] = GyroXb[3];
multiSensorpacket[24] = GyroYb[0];
multiSensorpacket[25] = GyroYb[1];
multiSensorpacket[26] = GyroYb[2];
multiSensorpacket[27] = GyroYb[3];
multiSensorpacket[28] = GyroZb[0];
multiSensorpacket[29] = GyroZb[1];
multiSensorpacket[30] = GyroZb[2];
multiSensorpacket[31] = GyroZb[3];
multiSensorpacket[32] = MagXb[0];
multiSensorpacket[33] = MagXb[1];
multiSensorpacket[34] = MagXb[2];
multiSensorpacket[35] = MagXb[3];
multiSensorpacket[36] = MagYb[0];
multiSensorpacket[37] = MagYb[1];
multiSensorpacket[38] = MagYb[2];
multiSensorpacket[39] = MagYb[3];
multiSensorpacket[40] = MagZb[0];
multiSensorpacket[41] = MagZb[1];
multiSensorpacket[42] = MagZb[2];
multiSensorpacket[43] = MagZb[3];
}
void ADCread()
{
sensorValue[0] = analogRead(EMG_pin[0]);
sensorValue[1] = analogRead(EMG_pin[1]);
byte EMG1sigMSB = sensorValue[0]/256;
EMG1sigMSB << 4;
byte EMG1sigLSB = sensorValue[0]%256;
byte EMG2sigMSB = sensorValue[1]/256;
byte EMG2sigLSB = sensorValue[1]%256;
Signal[0] = EMG1sigMSB | EMG2sigMSB;
Signal[1] = EMG1sigLSB;
Signal[2] = EMG2sigLSB;
multiSensorpacket[sEMGildx + EMGcounter + EMGtimecounter] = EMGtime[0];
multiSensorpacket[sEMGildx + EMGcounter + EMGtimecounter +1] = EMGtime[1];
multiSensorpacket[sEMGildx + EMGcounter + EMGtimecounter +2] = EMGtime[2];
multiSensorpacket[sEMGildx + EMGcounter + EMGtimecounter +3] = EMGtime[3];
sEMG[EMGcounter] = Signal[0];
sEMG[EMGcounter+1] = Signal[1];
sEMG[EMGcounter+2] = Signal[2];
EMGcounter = EMGcounter + 3;
EMGtimecounter = EMGtimecounter + 1;
}
void reTime()
{
currentSensorMicroTimes = micros();
preMicroTime = micros();
Intervalcal();
}
void preTime()
{
proMicroTime = micros();
Timer();
SecTimer();
}