Before logging an issue, please update to the latest release of Visual Micro from the Downloads Page.

When Logging a Support Issue in the Forum, please ensure you have also:-

  • Enabled vMicro > Compiler > Show Build Properties
  • Re-Compile your program with these settings enabled
 
Save the new Output to a Text File and....
  • Click the Reply button and attach as .txt file OR
  • Click here to Email us with the file attached, and a link to your post
Support requests without the output above may be impossible to answer, so please help us to help you
 
Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Arduino Micro/Leonardo + FreeRTOS (Read 9276 times)
AviatorLeo
Newbies
*
Offline


Posts: 4
Joined: Jul 2nd, 2015
Arduino Micro/Leonardo + FreeRTOS
Jul 2nd, 2015 at 8:47pm
Print Post  
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    Smiley

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 (;Wink; //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 (;Wink
     {
           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 (;Wink
     {

           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 (;Wink
     {
           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(){}
  
Back to top
 
IP Logged
 
Tim@Visual Micro
Administrator
*****
Offline


Posts: 12076
Location: United Kingdom
Joined: Apr 10th, 2010
Re: Arduino Micro/Leonardo + FreeRTOS
Reply #1 - Jul 2nd, 2015 at 9:35pm
Print Post  
Hi,

1)

Try replacing while(!Serial) with delay(2000)

2)

I don't know the micro very well or the BT board but I looked at the examples for the BT board and the definition of the arguments of the call you are making. 

However if ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST are pin numbers I can tell you that 0 and 1 are the HardwareSerial pins.

This is the default from the library examples on git:-

// Connect CLK/MISO/MOSI to hardware SPI
// e.g. On UNO & compatible: CLK = 13, MISO = 12, MOSI = 11
#define ADAFRUITBLE_REQ 10
#define ADAFRUITBLE_RDY 2     // This should be an interrupt pin, on Uno thats #2 or #3
#define ADAFRUITBLE_RST 9

Does the micro have an alternative spare interrupt pin for ADAFRUITBLE_RDY?

  
Back to top
WWW  
IP Logged
 
AviatorLeo
Newbies
*
Offline


Posts: 4
Joined: Jul 2nd, 2015
Re: Arduino Micro/Leonardo + FreeRTOS
Reply #2 - Jul 3rd, 2015 at 2:24pm
Print Post  
Hi, 

1)

I replaced the while(!Serial) and now it kind of works. At least is now starts my motor. Thanks =D

2)

Yes, Arduino Micro actually has 5 interrupt pins. Nevertheless I have every pin occupied with other tasks.
Also, on the tutorial of Adafruit for the BT board (https://learn.adafruit.com/getting-started-with-the-nrf8001-bluefruit-le-breakou...) it said that those pins could be changed, so it is not a problem I used other pins. The RDY had to be an interrupt pin and the Arduino Micro has int0 (pin 3), int1 (pin 2), int2 (pin 0), int3 (pin 1), int4 (pin 7).
  
Back to top
 
IP Logged
 
Tim@Visual Micro
Administrator
*****
Offline


Posts: 12076
Location: United Kingdom
Joined: Apr 10th, 2010
Re: Arduino Micro/Leonardo + FreeRTOS
Reply #3 - Jul 3rd, 2015 at 2:27pm
Print Post  
Yes you can not use pins 0 and 1 if you also want to use Serial so sounds like you have run out of pins. 

Are you using all the analog pins? They can be used as digital.
  
Back to top
WWW  
IP Logged
 
AviatorLeo
Newbies
*
Offline


Posts: 4
Joined: Jul 2nd, 2015
Re: Arduino Micro/Leonardo + FreeRTOS
Reply #4 - Jul 3rd, 2015 at 2:29pm
Print Post  
Yes I am using all my analog pins analog pins. And because of the board pin layout, some Digital Pins double as analog, which I am using too. 

And the Serial I am using is through the USB port, does it matter?
  
Back to top
 
IP Logged
 
Tim@Visual Micro
Administrator
*****
Offline


Posts: 12076
Location: United Kingdom
Joined: Apr 10th, 2010
Re: Arduino Micro/Leonardo + FreeRTOS
Reply #5 - Jul 3rd, 2015 at 2:33pm
Print Post  
Unfortunately the usb is connected to pin 0 and 1
  
Back to top
WWW  
IP Logged
 
AviatorLeo
Newbies
*
Offline


Posts: 4
Joined: Jul 2nd, 2015
Re: Arduino Micro/Leonardo + FreeRTOS
Reply #6 - Jul 3rd, 2015 at 2:40pm
Print Post  
Thanks Smiley

Ok, that USB connection is actually going to disappear. That is the reason for the BT breakout board, and that BT board communicates with the Arduino via SPI. Will it matter then? Because then my problem is again that the BT code crashes the program.
  
Back to top
 
IP Logged
 
Tim@Visual Micro
Administrator
*****
Offline


Posts: 12076
Location: United Kingdom
Joined: Apr 10th, 2010
Re: Arduino Micro/Leonardo + FreeRTOS
Reply #7 - Jul 3rd, 2015 at 2:48pm
Print Post  
I'm not sure. I suspect that if you have not used Serial.begin() you might be okay. You can try it by commenting the serial code.
  
Back to top
WWW  
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint