Hello,
As you already may know Arduino Micro/Leonardo has a 32u4 microcontroller. This allows native USB communication, but also handles serial communication different from boards based on 328 microcontroller.
I'm using FreeRTOS for my project and everything was working fine on my Arduino Uno, but now that I changed to the Arduino Micro (for miniaturizing and Nano was not available at the time of the purchase) serial communication works erratically. My program does not work unless I have serial communication opened, and I need it to work weather I have serial port opened or not, just like in the Uno. This problem is while using Arduino IDE or Matlab (I want Matlab communication). Strangely, using VisualMicro works just fine. What I have noticed is that the queue I'm using in the RTOS gets flooded when serial is not opened and messes with the execution of the OS. Is there a way to fix this without changing microcontroller?
Second. I'm trying to use a Bluetooth LE nRF8001 from Adafruit and when initializing the device my RTOS doesn't start correctly. Any clues?
Thanks
The code
//-- Libraries --
#include "FreeRTOS_AVR.h"
#include "basic_io_avr.h"
#include <SPI.h>
#include <Wire.h>
#include <Stepper.h>
#include <assert.h>
#include "Adafruit_BLE_UART.h"
//-- Declarations --
//Motor
int motorSpeed = 150; //Speed in RPM
const int stepsPerRevolution = 200;//Number of steps per revolution of the motor
//Sensors' Pins
int flex1 = 0; //Sensor 1 pin 0 analog
int flex2 = 1;
int flex3 = 2;
int flex4 = 3;
int flex5 = 4;
int flex6 = 5;
int flex7 = 6;
int flex8 = 7;
//Bluetooth
#define ADAFRUITBLE_REQ 2
#define ADAFRUITBLE_RDY 0
#define ADAFRUITBLE_RST 1
Adafruit_BLE_UART uart = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST); //This is the line that messes with the RTOS
//Motor Def
Stepper myStepper(stepsPerRevolution, 7, 8, 10, 11); //Define the steps per revolution and the pins
//Others
uint32_t temps = 0; //Time stamp for Matlab. Just declared once
//RTOS Task definition
void vMotorTask(void *pvParameters);
void vSensorTask(void *pvParameters);
void vMatlabTask(void *pvParameters);
void vBLETask(void *parameters);
//Tests for RTOS
const char *pcTextForMotorTask = "MotorTask\r\n";
const char *pcTextForSensorTask = "Sensor Task\r\n";
const char *pcTextForMatlabTask = "MatlabTask\r\n";
const char *pcTextForBLETask = "BLE\r\n";
//-- Handler Init --
xQueueHandle xQueue1;
/*********/
This function is called whenever select ACI events happen
/********/
void aciCallback(aci_evt_opcode_t event)
{
switch (event)
{
case ACI_EVT_DEVICE_STARTED:
Serial.println(F("Advertising started"));
break;
case ACI_EVT_CONNECTED:
Serial.println(F("Connected!"));
break;
case ACI_EVT_DISCONNECTED:
Serial.println(F("Disconnected or advertising timed out"));
break;
default:
break;
}
}
//-- Initialization --
void setup()
{
//MatLab
assert(sizeof(uint32_t) == sizeof(unsigned long)); //change the length of the data to be transmitted to Matlab
//Serial Communication
Serial.begin(9600); //transmission speed in bits per seconds
while (!Serial);
//Bluetooth
//uart.setACIcallback(aciCallback);
//uart.setDeviceName("AIS_PRO"); /* 7 characters max! */
//uart.begin();
//Queue
xQueue1 = xQueueCreate(64, sizeof(float));
//Motor
myStepper.setSpeed(motorSpeed);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
//Sensors
pinMode(flex1, INPUT); //Declare sensor pins as inputs. Declare as many as needed
pinMode(flex2, INPUT);
pinMode(flex3, INPUT);
pinMode(flex4, INPUT);
pinMode(flex5, INPUT);
pinMode(flex6, INPUT);
pinMode(flex7, INPUT);
pinMode(flex8, INPUT);
//RTOS Task Creation
if (xQueue1 != NULL)
{
xTaskCreate(vMotorTask, (signed char*) "Motor", 200, (void*)pcTextForMotorTask, 2, NULL);
xTaskCreate(vSensorTask, (signed char*) "Sensor Read", 300, (void*)pcTextForSensorTask, 2, NULL);
xTaskCreate(vMatlabTask, (signed char*) "Matlab Read", 300, (void*)pcTextForMatlabTask, 2, NULL);
//xTaskCreate(vBLETask, (signed char*) "BLE", 300, (void*)pcTextForBLETask, 2, NULL);
vTaskStartScheduler(); //Starts the scheduler task
}
for (;
; //Infinite loop
// return 0;
}
//-- Tasks --
void BoucleMoteur() //function that will be used in the loop
{
myStepper.step(1660);
myStepper.step(-1660);
}
void vMotorTask(void *pvParameters)
{
char *pcTaskName;
pcTaskName = (char*)pvParameters;
digitalWrite(3, HIGH);
digitalWrite(5, HIGH);
for (;
{
if (!Serial)
{
vPrintString(pcTaskName);
BoucleMoteur(); //make the motor work!
vPrintString("Motor Running\r\n");
}
else
{
vPrintString(pcTaskName);
BoucleMoteur(); //make the motor work!
vPrintString("Motor Running\r\n");
}
}
}
void vSensorTask(void *pvParameters)
{
portTickType xLastWakeTime;
char *pcTaskName;
float Sensor1, Sensor2, Sensor3, Sensor4, Sensor5, Sensor6;
portBASE_TYPE xStatus;
xLastWakeTime = xTaskGetTickCount();
pcTaskName = (char*)pvParameters;
for (;
{
if (!Serial)
{
vPrintString(pcTaskName);
Sensor1 = analogRead(flex1);//Sensor Read
Sensor2 = analogRead(flex2);
Sensor3 = analogRead(flex3);
Sensor4 = analogRead(flex4);
Sensor5 = analogRead(flex5);
Sensor6 = analogRead(flex6);
vTaskDelayUntil(&xLastWakeTime, (200 / portTICK_RATE_MS));
}
else
{
vPrintString(pcTaskName);
Sensor1 = analogRead(flex1);//Sensor Read
Sensor2 = analogRead(flex2);
Sensor3 = analogRead(flex3);
Sensor4 = analogRead(flex4);
Sensor5 = analogRead(flex5);
Sensor6 = analogRead(flex6);
xStatus = xQueueSendToBack(xQueue1, &Sensor1, 0);
xStatus = xQueueSendToBack(xQueue1, &Sensor2, 0);
xStatus = xQueueSendToBack(xQueue1, &Sensor3, 0);
xStatus = xQueueSendToBack(xQueue1, &Sensor4, 0);
xStatus = xQueueSendToBack(xQueue1, &Sensor5, 0);
xStatus = xQueueSendToBack(xQueue1, &Sensor6, 0);
if (xStatus != pdPASS)
{
/* We could not write to the queue because it was full, this must
be an error as the queue should never contain more than one item! */
vPrintString("Could not send to the queue.\r\n");
}
vTaskDelayUntil(&xLastWakeTime, (200 / portTICK_RATE_MS));
}
}
}
void vMatlabTask(void *pvParameters)
{
float RS1, RS2, RS3, RS4, RS5, RS6;
portBASE_TYPE xStatus;
const portTickType xTicksToWait = 300 / portTICK_RATE_MS;
char *pcTaskName;
pcTaskName = (char*)pvParameters;
for (;
{
if (!Serial)
{
vPrintString(pcTaskName);
}
else
{
vPrintString(pcTaskName);
if (uxQueueMessagesWaiting(xQueue1) != 0)
{
vPrintString("Queue should have been empty!\r\n");
}
xStatus = xQueueReceive(xQueue1, &RS1, xTicksToWait);
xStatus = xQueueReceive(xQueue1, &RS2, xTicksToWait);
xStatus = xQueueReceive(xQueue1, &RS3, xTicksToWait);
xStatus = xQueueReceive(xQueue1, &RS4, xTicksToWait);
xStatus = xQueueReceive(xQueue1, &RS5, xTicksToWait);
xStatus = xQueueReceive(xQueue1, &RS6, xTicksToWait);
if (xStatus == pdPASS)
{
vPrintStringAndNumber("Received 1= ", RS1);
vPrintStringAndNumber("Received 2= ", RS2);
vPrintStringAndNumber("Received 3= ", RS3);
vPrintStringAndNumber("Received 4= ", RS4);
vPrintStringAndNumber("Received 5= ", RS5);
vPrintStringAndNumber("Received 6= ", RS6);
}
else
{
vPrintString("Could not receive from the queue.\r\n");
}
temps = millis();
Serial.write('z'); //send the character z through the serial (it's the signal that starts Matlab program)
Serial.write((uint8_t*)&temps, sizeof(temps)); //sends the time with the right format
Serial.write((uint8_t*)&RS1, sizeof(uint16_t)); //sends the sensor data with the right format
Serial.write((uint8_t*)&RS2, sizeof(uint16_t));
Serial.write((uint8_t*)&RS3, sizeof(uint16_t));
Serial.write((uint8_t*)&RS4, sizeof(uint16_t));
Serial.write((uint8_t*)&RS5, sizeof(uint16_t));
Serial.write((uint8_t*)&RS6, sizeof(uint16_t));
}
}
}
void loop(){}