Driving a TMC5160 from ESP32 - driver

I am trying to use the TMC5160 library by Tom Magnier and having a couple of issues. I am using the SPI interface version of the BigTreeTech chip and have the following pins hooked up.
Hardware setup :
MOSI (ESP32 : 23) <=> SDI
MISO (ESP32 : 19) <=> SDO
SCK (ESP32 : 18) <=> SCK
ESP32:5 <=> CSN
ESP32:25 <=> DRV_ENN (optional, tie to GND if not used)
GND <=> GND
3.3V (ESP32 : ) <=> VCC_IO (depending on the processor voltage)
I am basically just trying to implement the sample and it appears I can configure the driver with the defaults as it finds the chip and shows status. But, it will not respond to motor control. I am wondering if I am missing something in the connection to the ESP32.
My code for initialization and testing.
void izTMC5160::Initialize()
{
_log->Log("izTMC5160::Initialize starting...");
pinMode(_enablePin, OUTPUT);
digitalWrite(_enablePin, LOW); // Active low
SPI.begin();
// This sets the motor & driver parameters /!\ run the configWizard for your driver and motor for fine tuning !
powerStageParams.drvStrength = 2;
powerStageParams.bbmTime = 24;
powerStageParams.bbmClks = 0;
motorParams.globalScaler = 219;
motorParams.irun = 31;
motorParams.ihold = 15;
// motorParams.freewheeling = 0;
motorParams.pwmOfsInitial = 30;
motorParams.pwmGradInitial = 0;
motor.begin(powerStageParams, motorParams, TMC5160::NORMAL_MOTOR_DIRECTION);
// ramp definition
motor.setRampMode(TMC5160::POSITIONING_MODE);
motor.setMaxSpeed(_maxSpeed);
motor.setAcceleration(_acceleration);
delay(_startupDelay); // Standstill for automatic tuning
_log->Log("izTMC5160::Initialize completed...");
}
void izTMC5160::Test()
{
_testDir = !_testDir;
motor.setTargetPosition(_testDir ? _testSteps : -_testSteps); // 1 full rotation = 200s/rev
float xactual = motor.getCurrentPosition();
float vactual = motor.getCurrentSpeed();
char buffer[256];
sprintf(buffer, "izTMC5160::Test - Current position: %f Current Speed: %f",xactual,vactual);
_log->Log(buffer);
}
void izTMC5160::Enable(bool enable)
{
if(enable)
{
digitalWrite(_enablePin,LOW);
}
else
{
digitalWrite(_enablePin,HIGH);
}
}

the example works,
my guess is you have not enabled motion control mode.
the bigtree tech tmc5160 doesnt offer an easy way to adjust spi and sd mode selectors,there version one did hopefully the next batch will also.
see here for fix :https://github.com/bigtreetech/BIGTREETECH-TMC5160-V1.0/issues/8

Related

BNO055 to control Nema 17 stepper motor with a4988 driver via rosserial

My goal is to control the position and speed of a Nema 17 stepper motor based on the euler angle of a BNO055 inertial measurement unit. I am using an ESP32 to flash the code via WIFI to rosserial. I am powering the Nema 17 with a 12V power source and the BNO055 with a small external 5V battery pack.
In summary, the stepper motor should move between 0-4100 steps which would be mapped to -90 and 90 degrees of the BNO055's y-axis.
For this, I need to read the output of the BNO055 sensor as often as possible and only change directions of the Nema 17 when the BNO055 has changed position relative to the mapping.
The PROBLEM I am having is that when I incorporate reading the sensor in my code, my motor starts to shake and does not rotate smoothly. I am wondering how I can get both things to work simultaneously (reading sensor and moving nema 17).
PS: I will control speed by calculating a PI control with the BNO055 sensor and adjusting the delayMicroseconds() accordingly... but first thing is to get the readings and motor movement smooth.
Below is a code snippet I am using to debug this problem:
#include <WiFi.h>
#include <ros.h>
#include <Wire.h>
#include <std_msgs/Header.h>
#include <std_msgs/String.h>
#include <geometry_msgs/Quaternion.h>
#include <HardwareSerial.h>
#include <analogWrite.h>
#include <MultiStepper.h>
#include <AccelStepper.h>
#include <Stepper.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <math.h>
//////////////////////
// BNO055 //
//////////////////////
Adafruit_BNO055 bno_master = Adafruit_BNO055(55, 0x29);
Adafruit_BNO055 bno_slave = Adafruit_BNO055(55, 0x28);
geometry_msgs::Quaternion Quaternion;
std_msgs::String imu_msg;
#define I2C_SDA 21
#define I2C_SCL 22
TwoWire I2Cbno = TwoWire(0); // I2C connection will increase 6Hz data transmission
float ax_m, ay_m, az_m, ax_s, ay_s, az_s; // accelerometer
float gw_m, gx_m, gy_m, gz_m, gw_s, gx_s, gy_s, gz_s; // gyroscope
float ex_m, ey_m, ez_m, ex_s, ey_s, ez_s; // euler
float qw_m, qx_m, qy_m, qz_m, qw_s, qx_s, qy_s, qz_s; // quaternions
//////////////////////
// WiFi Definitions //
//////////////////////
const char* ssid = "FRITZ!Box 7430 PN"; // Sebas: "WLAN-481774"; Paula: "FRITZ!Box 7430 PN"; ICS: ICS24; Hotel Citadelle Blaye
const char* password = "37851923282869978396"; // Sebas: "Kerriganrocks!1337"; Paula: "37851923282869978396"; ICS: uZ)7xQ*0; citadelle
IPAddress server(192,168,178,112); // ip of your ROS server
IPAddress ip_address;
WiFiClient client;
int status = WL_IDLE_STATUS;
//long motorTimer = 0, getImuDataTimer = 0, millisNew = 0; //millisOld = 0,
//////////////////////
// Stepper motor //
//////////////////////
int stepPin = 4;
int stepPinState = LOW;
int dirPin = 2;
int dirPinState = HIGH;
unsigned long millisOld1 = 0;
unsigned long millisOld2 = 0;
long motorTimer = 1; // in milliseconds
long getImuDataTimer = 10; // in milliseconds
double maxPosition = 4100;
double stepsMoved = 0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class WiFiHardware {
public:
WiFiHardware() {};
void init() {
// do your initialization here. this probably includes TCP server/client setup
client.connect(server, 11411);
}
// read a byte from the serial port. -1 = failure
int read() {
// implement this method so that it reads a byte from the TCP connection and returns it
// you may return -1 is there is an error; for example if the TCP connection is not open
return client.read(); //will return -1 when it will works
}
// write data to the connection to ROS
void write(uint8_t* data, int length) {
// implement this so that it takes the arguments and writes or prints them to the TCP connection
for(int i=0; i<length; i++)
client.write(data[i]);
}
// returns milliseconds since start of program
unsigned long time() {
return millis(); // easy; did this one for you
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int i;
void chatterCallback(const std_msgs::String& msg) {
i = atoi(msg.data);
// s.write(i);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setupWiFi()
{
// WIFI setup
WiFi.begin(ssid, password);
Serial.print("\nConnecting to "); Serial.println(ssid);
uint8_t i = 0;
while (WiFi.status() != WL_CONNECTED && i++ < 20) delay(500);
if(i == 21){
Serial.print("Could not connect to"); Serial.println(ssid);
while(1) delay(500);
}
Serial.print("Ready! Use ");
Serial.print(WiFi.localIP());
Serial.println(" to access client");
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ros::Subscriber<std_msgs::String> sub("message", &chatterCallback);
ros::Publisher pub("imu_data/", &imu_msg);
ros::NodeHandle_<WiFiHardware> nh;
void setup() {
// set the digital pins as outputs
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
Serial.begin(57600);
setupWiFi();
// I2C connection IMUs
Wire.begin(I2C_SDA, I2C_SCL);
I2Cbno.begin(I2C_SDA, I2C_SCL, 400000);
bno_master.begin();
bno_slave.begin();
// get imu calibrations
uint8_t system, gyro, accel, mg = 0;
bno_master.getCalibration(&system, &gyro, &accel, &mg);
bno_slave.getCalibration(&system, &gyro, &accel, &mg);
bno_master.setExtCrystalUse(true);
bno_slave.setExtCrystalUse(true);
nh.initNode();
nh.advertise(pub);
}
/////////////////////////////
/// GET IMU DATA FUNCTION ///
/////////////////////////////
int get_imu_data(){
imu::Vector<3> Euler_s = bno_slave.getVector(Adafruit_BNO055::VECTOR_EULER); // 100 Hz capacity by BNO055 // IF I COMMENT THIS LINE OUT AND SET VARIABLES BELOW TO SET VALUES, MY MOTOR RUNS PERFECTLY
// Euler
float ex_s = Euler_s.x();
float ey_s = Euler_s.y();
float ez_s = Euler_s.z();
// putting data into string since adding accel, gyro, and both imu data becomes too cumbersome for rosserial buffer size. String is better for speed of data
String data = String(ex_s) + "," + String(ey_s) + "," + String(ez_s) + "!";
int length_data = data.indexOf("!") + 1;
char data_final[length_data + 1];
data.toCharArray(data_final, length_data + 1);
imu_msg.data = data_final;
pub.publish(&imu_msg);
nh.spinOnce();
Serial.println(ey_s);
return ey_s; // ex_s, ey_s, ez_s
}
/////////////////////////////
// MAIN LOOP //
/////////////////////////////
void loop() {
unsigned long currentMillis = millis();
//////////////////
// GET IMU DATA //
//////////////////
if(currentMillis - millisOld2 >= getImuDataTimer)
{
ey_s = get_imu_data();
Serial.print(ey_s);
}
////////////////
// MOVE MOTOR //
////////////////
// later, the direction will depend on the output of ey_s
if((dirPinState == HIGH) && (currentMillis - millisOld1 >= motorTimer))
{
if(stepsMoved <= maxPosition)
{
digitalWrite(dirPin, dirPinState);
millisOld1 = currentMillis; // update time
stepsMoved += 5;
for(int i =0; i<=5; i++)
{
digitalWrite(stepPin, HIGH);
delayMicroseconds(1200); // constant speed
digitalWrite(stepPin, LOW);
}
Serial.println(stepsMoved); // checking
}
else if(stepsMoved > maxPosition)
{
dirPinState = LOW;
millisOld1 = currentMillis; // update time
stepsMoved = 0;
}
}
if((dirPinState == LOW) && (currentMillis - millisOld1 >= motorTimer))
{
if(stepsMoved <= maxPosition)
{
digitalWrite(dirPin, dirPinState);
millisOld1 = currentMillis; // update time
stepsMoved += 5;
for(int i =0; i<=5; i++)
{
digitalWrite(stepPin, HIGH);
delayMicroseconds(1200); // constant speed
digitalWrite(stepPin, LOW);
}
Serial.println(stepsMoved); // checking
}
else if(stepsMoved > maxPosition)
{
dirPinState = HIGH;
millisOld1 = currentMillis; // update time
stepsMoved = 0;
}
}
}
I have tried the AccelStepper.h library but not getting the outputs desired in terms of position control and speed updates.
Arduino's all-in-one loop() is not the correct architecture for controlling real-time systems. Motor control requires rather accurate timing - e.g. looks like you wish to update motor control output with a frequency of 833 Hz (from the 1.2 ms delay) which should then be fairly accurate and stable.
Unfortunately you're not getting anywhere near this, as you're doing a bunch of non-critical stuff in each loop which potentially takes a very long (and undeterministic) amount of time - waiting for the IMU to give you a sample, printing to the serial port, talking to some ROS component, etc. Meanwhile the real-time critical control signal to your motor is waiting for all this to finish before it can do its work. Note that printing a few lines to the serial could already take dozens of milliseconds, so your delayMicroseconds(1200); is analogous to measuring a cut with a caliper and then making the cut with an axe with your eyes closed.
A real-time critical process should execute in its own thread which has higher priority than the non-real-time critical stuff. In your case it should probably run off a timer with a 1.2 ms period. The timer handler should execute with higher priority than all the other stuff, calculate desired output to motor using last received sensor input (i.e. don't go asking the IMU for a fresh reading when it's time to move the motor) and exit.
Then you can run all the other stuff from the loop() in idle priority which simply gets pre-empted when the motor control does its work.
Depending on how critical the accurate timing of IMU input is, you may want to run this also in a separate thread with a priority somewhere between the motor control interrupt and idle (remember to yield some CPU cycles to loop() or it'll starve).

CORTEX_M4_0: error occurs in GPIO code in debug mode

I am having this error whenever I try to debug my program using Code Composer Studio V 9.1.0 :
CORTEX_M4_0: Trouble Reading Memory Block at 0x400043fc on Page 0 of Length 0x4: Debug Port error occurred
I am using a Texas Instruments TM4C123GXL launchpad, and it connects to my laptop via a USB cable. I can successfully build my program, but the errors show up whenever I try to debug my program. My program is supposed to use SysTick interrupts to continuously vary the voltage on an Elegoo membrane switch module to allow the program to see which button I've pressed. I'm not 100% sure I've correctly initialized the GPIO input and output ports, but the errors occur before the program even starts and reaches my main loop.
Here is a screenshot of some code and my errors:
Here is some code:
void SysTickInit()
{
NVIC_ST_CTRL_R = 0;
NVIC_ST_RELOAD_R = 0x0C3500; // delays for 10ms (800,000 in hex) '0x0C3500' is
// original correct
NVIC_ST_CURRENT_R = 0;
NVIC_ST_CTRL_R = 0x07; // activates the systick clock, interrupts and enables it again.
}
void Delay1ms(uint32_t n)
{
uint32_t volatile time;
while (n)
{
time = 72724 * 2 / 91; // 1msec, tuned at 80 MHz
while (time)
{
time--;
}
n--;
}
}
void SysTick_Handler(void) // this function is suppose to change which port
// outputs voltage and runs every time systick goes
// to zero
{
if (Counter % 4 == 0)
{
Counter++;
GPIO_PORTA_DATA_R &= 0x00; // clears all of port A ( 2-5)
GPIO_PORTA_DATA_R |= 0x04; // activates the voltage for PORT A pin 2
Delay1ms(990);
}
else if (Counter % 4 == 1)
{
Counter++;
GPIO_PORTA_DATA_R &= 0x00; // clears all of port A (2-5)
GPIO_PORTA_DATA_R |= 0x08; // activates voltage for PORT A pin 3
Delay1ms(990);
}
else if (Counter % 4 == 2)
{
Counter++;
GPIO_PORTA_DATA_R &= 0x00; // clears all of port A (2-5)
GPIO_PORTA_DATA_R |= 0x10; // activates voltage for PORT A pin 4
Delay1ms(990);
}
else if (Counter % 4 == 3)
{
Counter++;
GPIO_PORTA_DATA_R &= 0x00; // clears all of port A (2-5)
GPIO_PORTA_DATA_R |= 0x20; // activates voltage for PORT A pin 5
Delay1ms(990);
}
}
void KeyPadInit()
{
SYSCTL_RCGCGPIO_R |= 0x03; // turns on the clock for Port A and Port B
while ((SYSCTL_RCGCGPIO_R) != 0x03) { }; // waits for clock to stabilize
GPIO_PORTA_DIR_R |= 0x3C; // Port A pins 2-5 are outputs (i think)
GPIO_PORTA_DEN_R |= 0x3C; // digitally enables Port A pins 2-5
GPIO_PORTA_DIR_R &= ~0xC0; // makes Port A pin 6 and 7 inputs
GPIO_PORTA_DEN_R |= 0XC0; // makes Port A pin 6 and 7 digitally enabled
GPIO_PORTB_DIR_R &= ~0X03; // makes Port B pin 0 and 1 inputs
GPIO_PORTB_DEN_R |= 0x03; // makes PortB pin 0 and 1 digitally enabled
}
I found out why my error was occurring. I went to my professor and he had a custom-built device to check if my pins on my launchpad were working. It turns out some of the pins I was using on Port A and B drew too much current, and according to the custom-built device, became busted. In other words, this error came about because the IDE detected that some of my pins weren't operational anymore.
In my case I had to disable the AHB (advanced high-performance bus) in the GPIOHBCTL register to read the GPIO_PORTx register. If you want to read the register when the AHB is activated you must read the GPIO_PORTx_AHB register.
Access to GPIO_PORTA_AHB register when AHB is activated - it works
Access to GPIO_PORTA register when AHB is activated - it fails
The Solution is to enable The clock getting into the peripheral using the RCC Section

Stm32f4 dma m2m

I'm using STM32F407VG Discovery Board and I've issue with DMA memory to memory transfer. I want to copy 32 bytes of data from one place in memory to other using DMA by writing copy_dma() function. In while loop i'm checking Transfer Complete flag but DMA never returns it. I want to ask where i'm making mistake? Maybe something in configuration is wrong. I'm using Standart Peripheral Libraries. Here's my code.
#include "stm32f4xx.h"
#define BUFFER_SIZE 32
uint8_t src_buffer[BUFFER_SIZE];
uint8_t dst_buffer[BUFFER_SIZE];
void copy_dma(void);
int main(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
int i;
DMA_InitTypeDef dma;
DMA_DeInit(DMA1_Stream4);
DMA_StructInit(&dma);
dma.DMA_Channel = DMA_Channel_1;
dma.DMA_PeripheralBaseAddr = (uint32_t)src_buffer;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
dma.DMA_Memory0BaseAddr = (uint32_t)dst_buffer;
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_BufferSize = BUFFER_SIZE;
dma.DMA_DIR = DMA_DIR_MemoryToMemory;
dma.DMA_FIFOMode = DMA_FIFOMode_Disable;
dma.DMA_MemoryBurst = DMA_MemoryBurst_Single;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma.DMA_Mode = DMA_Mode_Normal;
dma.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Stream4, &dma);
for (i = 0; i < BUFFER_SIZE; i++) {
src_buffer[i] = 100 + i;
}
copy_dma();
while(1) {
}
}
void copy_dma(void) {
DMA_Cmd(DMA1_Stream4, ENABLE);
while (DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_TCIF4) == RESET);
}
In app note "Using the STM32F2 and STM32F4 DMA controller"(http://stm32.eefocus.com/download/index.php?act=down&id=6312)
is mentioned:
"Memory to memory (only DMA2 is able to do such transfer, in this mode, the circular and direct modes are not allowed.)"
So, try to use DMA2.
In addition to Mariusz Górka's awnser:
When using the DMA you need to know which memory region you are using. The stm32f4 has a memory section called Core Coupled Memory (CCM). The DMA does not have access to this region.
Check your map file and make sure your buffers are not in the region 0x10000000 - 0x1000FFFF.

XBee printout, void setup()

I'm having trouble with my XBee's printing out to the monitor a simple statement, within the void setup(), as shown in my program below.
It prints the GPS and various sensor data, but it skips the whole introductory sentences. Whenever I open the arduino serial monitor, with the board plugged into my computer, it works fine.
Any suggestions? I'm at a lost!
Thanks :)
// Temperature Sensor data, Air Quality, and GPS data update XBEE
//CSV format for user interpretation
//Last updated 11/5/14
//Amy Laguna
#include <Adafruit_GPS.h>
#include <math.h>
#include <SoftwareSerial.h>
SoftwareSerial XBee(2, 3);
SoftwareSerial mySerial(8, 7);
//Read temperature sensor on A1
int tempPin = 1;
//Read CO sensor on A0
int coPin = 0;
//Read Oxygen sensor on A2
int opin = 2;
//GPS setup
Adafruit_GPS GPS(&mySerial);
//Use to debug
//SET to 'fale' to turn off echoing the GPS data to Serial
//Set to 'true' to debug and listen to raw GPS data
#define GPSECHO false
// this keeps track of whether we're using the interrupt
boolean usingInterrupt = false;
void useInterrupt(boolean);
void setup()
{
// connect at 115200 so we can read the GPS fast enough and echo without dropping chars
XBee.begin(115200);
Serial.begin(115200);
delay(5000);
XBee.println("Vehicle GPS, Temperature, and Air Quality Data!");
delay(2000);
XBee.println("Note: Elevation in Pensacola Florida: ~ 31 m (102 ft)");
XBee.println();
XBee.println("\n Date: Time: Fix: Location: Speed (mph): Elevation: CO: O2: Temperature: ");
// 9600 NMEA is the default baud rate for Adafruit MTK GPS's
GPS.begin(9600);
// RMC (recommended minimum) and GGA (fix data) including altitude
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
// Set the update rate
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
// For the parsing code to work nicely and have time to sort thru the data, and
// print it out we don't suggest using anything higher than 1 Hz
useInterrupt(true);
delay(1500);
}
// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
char c = GPS.read();
// if you want to debug, this is a good time to do it!
#ifdef UDR0
if (GPSECHO)
if (c) UDR0 = c;
#endif
}
void useInterrupt(boolean v) {
if (v) {
// Timer0 is already used for millis() - we'll just interrupt somewhere
// in the middle and call the "Compare A" function above
OCR0A = 0xAF;
TIMSK0 |= _BV(OCIE0A);
usingInterrupt = true;
} else {
// do not call the interrupt function COMPA anymore
TIMSK0 &= ~_BV(OCIE0A);
usingInterrupt = false;
}
}
uint32_t timer = millis();
void loop() // run over and over again
{
if (! usingInterrupt) {
// read data from the GPS in the 'main loop'
char c = GPS.read();
// if you want to debug, this is a good time to do it!
if (GPSECHO)
if (c) XBee.print(c);
}
// if a sentence is received, we can check the checksum, parse it...
if (GPS.newNMEAreceived()) {
if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
return; // we can fail to parse a sentence in which case we should just wait for another
}
// if millis() or timer wraps around, we'll just reset it
if (timer > millis()) timer = millis();
// approximately every 2 seconds or so, print out the current stats
if (millis() - timer > 2000) {
timer = millis(); // reset the timer
PrintGPS(); //Print GPS readings
PrintAirQuality(); //Print CO and Temperature readings
}
}
void PrintGPS()
{
//Print Date, Time, Fix
XBee.print("\n");
XBee.print(GPS.month, DEC); XBee.print('/');
XBee.print(GPS.day, DEC); XBee.print("/20");
XBee.print(GPS.year, DEC);
XBee.print(" , ");
XBee.print(GPS.hour, DEC); XBee.print(':');
XBee.print(GPS.minute, DEC); XBee.print(':');
XBee.print(GPS.seconds, DEC);
}
Maybe try a longer delay before the XBee.println() statements. If the radio modules haven't associated yet, they won't be ready for you to start sending data through them.
Alternatively, wait until the first call to PrintGPS() and send it then:
void PrintGPS()
{
static int first_time = 1;
if (first_time) {
print_headers();
first_time = 0;
}
//Print Date, Time, Fix
...

Parsing serial string data into an array (VVVV to Arduino)

I'm currently working on an arduino project at University. Basically what I am trying to do is send a string of data from VVVV to arduino, however I need to parse the data into an array and I have absolutely no idea how to do this!
The string being sent from VVVV is something like this; U,c,R,|,W,H,P and I need each of those values to be written to a specific servo each time, so value 1 need to go to servo 1, and so on.
Here is my code at the moment, I realize its coded pretty badly, and I do intend to make to make it more efficient when I have worked out how to parse the data.
#include <Servo.h>
Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
char array1[4] = { '0', '0', '0', '0'}; //array for midi variables
void setup()
{
// begin the serial communication
Serial.begin(9600);
servo1.attach(2);
servo2.attach(3);
servo3.attach(4);
servo4.attach(5);
}
void loop(){
while (Serial.available() == 0) {
array1[0] = 0;
array1[1] = 0;
array1[2] = 0;
array1[3] = 0;
}
{
// check if data has been sent from the computer
if (Serial.available() >= 4) {
for ( int i = 0; i < 4; i++)
array1[i] = Serial.read();
}
Serial.print(array1[0]);
Serial.print(array1[1]);
Serial.print(array1[2]);
Serial.print(array1[3]);
servo1.write(array1[0]);
servo2.write(array1[1]);
servo3.write(array1[2]);
servo4.write(array1[3]);
}
}
Edit - I should probably mention that I'm eventually looking to use 7 servos, but for the moment I'm just using 4 in my circuit. Also, when I upload this patch and enable VVVV, the arduino just disconnects.
#opc0de This serial issue has cause a lot of confusion. Including to myself. Possibly similar issue here.
I recently dabbled into this. The Arduino automatically resets when it receives serial
communication from most things other than the Arduino IDE. This is why
you can send from the IDE but not node.js.
I have an Uno and put a capacitor between Reset and Ground.Here's a
page with some good info on the subject. Good luck.
http://arduino.cc/playground/Main/DisablingAutoResetOnSerialConnection
if (Serial.available() > 3)
{
for (int i=0; i < 4 ; i++)
{
array[i] = Serial.read();
}
Serial.flush();
}
Hope it helps !
If you want to assign the value as soon as received, you can do this:
if(Serial.available() >= 3) {
servo1.write(Serial.read());
servo2.write(Serial.read());
servo3.write(Serial.read());
servo4.write(Serial.read());
Serial.flush();
}
If you want to have the received values stored on the array to do something more later, then:
if(Serial.available() >= 3) {
for(i = 0; i < 4; i ++) {
array[i] = Serial.read();
}
Serial.flush();
}

Resources