I am trying to control a Reaction Wheel Inverted Pendulum using SimpleFOCShield in real-time through Simulink. I have tried porting the SimpleFOCLibrary to Simulink as a S-function, but it hasn’t worked out. That’s why I took another approach, which is to upload the program through Arduino IDE. And then control the motor from Simulik instead of SimpleFOCStudio.
I am not that familiar with Serial Communication between Arduino IDE and Simulink, but I have seen a few examples online. I am trying to do the serial communication step by step. Right now I am trying to control the torque/voltage using the serial communication from simulink as the input for the target voltage. But the motor is not spinning. I took a part of the ReactionWheel example code and what I did was as the following:
#include <SimpleFOC.h>
// Create a union to easily convert float to byte
typedef union{
float number;
uint8_t bytes[4];
} FLOATUNION_t;
// Create the variable you want to send
FLOATUNION_t myValue;
// init BLDC motor
BLDCMotor motor = BLDCMotor( 14 );
// init driver
BLDCDriver3PWM driver = BLDCDriver3PWM(5, 9, 6, 8);
// init encoder
Encoder encoder = Encoder(3, 2, 2048);
// channel A and B callbacks
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}
// pendulum encoder init
Encoder pendulum = Encoder(A0, A2, 2048);
// interrupt routine
void doPA(){pendulum.handleA();}
void doPB(){pendulum.handleB();}
void setup() {
// initialize motor encoder hardware
encoder.init();
encoder.enableInterrupts(doA,doB);
// driver config
driver.voltage_power_supply = 12;
driver.init();
// init the pendulum encoder
pendulum.init();
pendulum.enableInterrupts(doPA,doPB);
// set control loop type to be used
motor.torque_controller = TorqueControlType::voltage;
motor.controller = MotionControlType::torque;
Serial.begin(115200);
// link the motor to the encoder
motor.linkSensor(&encoder);
// link the motor to the driver
motor.linkDriver(&driver);
// initialize motor
motor.init();
// align encoder and start FOC
motor.initFOC();
}
void loop() {
// iterative FOC function
motor.loopFOC();
float target_voltage;
target_voltage = getFloat();
delay(1);
// pendulum sensor read
pendulum.update();
// position motion control loop
motor.move(target_voltage);
}
float getFloat(){
int cont = 0;
FLOATUNION_t f;
while (cont < 4 ){
f.bytes[cont] = Serial.read() ;
cont = cont +1;
}
return f.number;
}
I am trying to control or for now send data/value from one STM32-L476RG board with another using UART/USART. I have attached the Rx pin of the "master" to the Tx of the "slave" and vice versa.
The "master" board will be controlled from Simulink similar to this first model of this example. While the "slave" board will be flashed from Arduino IDE, because of compatibility issues with another library that will be added if this is a success.
I tried running the code below, but there seems to be no data received by the "slave" board, which I checked through the serial monitor of Arduino IDE. Could you please help me identify the problem that might cause this? Thanks.
The Simulink model is as follows (The values are set to uint16_t):
I am currently trying to control Arduino Uno with STM32L47RG in Simulink via UART. But I think Arduino Uno isn't receiving any of the data. The STM32's Rx and Tx pins are connected to the Arduino Uno's Rx and Tx.
The Arduino code I wrote is referenced from the Arduino Cookbook , the Serial Input Basics, and this example.
I have used an oscilloscope to check whether it is sending the data, and there is data being sent as shown in the image below. Can anyone help identify where I got wrong?
/*
* SerialReceive sketch
* Blink the LED at a rate proportional to the received digit value
*/
const int ledPin = 13; // pin the LED is connected to
int blinkRate=0; // blink rate stored in this variable
void setup()
{
Serial.begin(115200); // Initialize serial port to send and receive at 9600 baud
pinMode(ledPin, OUTPUT); // set this pin as output
}
void loop()
{
if ( Serial.available()) // Check to see if at least one character is available
{
char ch = Serial.read();
if(ch >= '0' && ch <= '9') // is this an ascii digit between 0 and 9?
{
blinkRate = (ch - '0'); // ASCII value converted to numeric value
blinkRate = blinkRate * 100; // actual blinkrate is 100 mS times received digit
}
}
blink();
}
// blink the LED with the on and off times determined by blinkRate
void blink()
{
digitalWrite(ledPin,HIGH);
delay(blinkRate); // delay depends on blinkrate value
digitalWrite(ledPin,LOW);
delay(blinkRate);
}
You may damage the STM32 by connecting any of it's pins directly to an UNO. The UNO runs on 5V, the STM32 on 3.3V. You must use level converters between them to adapt the voltage.
Did you cross-over? So UNO's RX is connected to STM32's TX and vice-versa (by a level converter of course).
Thanks for the reply. I have decided to use 2 same STM32 boards instead of the Arduino UNO, to prevent that from happening. I have also find out that the default pins for Rx and Tx are not working properly, so I used the SoftwareSerial.h to use different ones.
You shouldn't start half a dozen thread for the same issue!
I have doubts that the software emulation works better. You may tell us what "are not working properly" means. You may have fried them by connecting directly to the UNO.
I am trying to send a uint16 value(converted to 2 bytes) from a STM32 board through Simulink using serial communication to a STM32 board programmed with Arduino IDE. At first, I was able to read the values being sent after being decoded, but after that the values are a mess. I was wondering if there are ways to help the board read the right bytes in the right order. I have read the Serial Input Basic, but with example 4, it uses a "\n" end marker, which is not possible in my case. I would greatly appreciate it if anyone could suggest a solution to this.
can you send the number in ASCII decimal representation and add the trailing line feed ?
then you don't have to worry wether it's a 2 or 4 byte integer, little or big endian etc and you have an end marker to get in sync with the sender
That only works if all systems have the same "endianness". If you send 0xAA, 0x55 to a Little-Endian processor you will get a value of 0x55AA. If you send it to a BigEndian processor you will get 0xAA55.
I think I can send the number in ASCII. I can convert it to string then convert it to ASCII, but I'm not sure if it's right, because there are no integer to ascii block. Unlike Arduino's Serial Transmit Block in Simulink, STM32's SCI Write block has no option to add trailing line feed. So I don't know how to add it yet.
it works indeed but yet in some cases it can fail (compiler adds padding etc). So best not to use it and do it the proper way with memcpy() and the compiler will do the right thing.
Did I understand that correctly, that's Simulink stuff? I have no clue about that one you might have to consult the manual or ask the manufacturer but I doubt that there's no way to do it. Otherwise that software is simply crap.