Basically I need two float values (azimuth, elevation) to be passed to a couple of stepper motors. I made a simple code and it's working if send commands over the Serial Monitor. The toFloat() method is coming from a patched String class http://www.timewasters-place.com/arduino-string-and-float/:
void loop()
{
while (Serial.available() > 0) {
float inChar = Serial.read();
// float val = Serial.parseFloat();
if (isDigit(inChar)) {
// convert the incoming byte to a char
// and add it to the string:
inString += (char)inChar;
}
// if you get a different char, print the string,
// then the string's value:
if (inChar == 'a') {
control = true;
azimuth = inString.toFloat();
Serial.print("AZ.Value:");
Serial.println(azimuth);
// clear the string for new input:
inString = "";
}
if (inChar == 'b') {
control = true;
elevation = inString.toFloat();
Serial.print("EL.Value:");
Serial.println(elevation);
// clear the string for new input:
inString = "";
}
}
}
Once I start sending values from the monitor like "30.0234b" or "45.456a", I get accurate values in the serial monitor like these:
EL.Value:30.02
AZ.Value:45.45
Motors move to their positions. Perfect!
However, when I run my Processing sketch and write every 2 secs changing values like this: port.write(75.4992+"a");port.write(45.463737+"b");, then I get into trouble. Motors will just move erratically. This is a section of my output:
Is it a problem of timing or of that patch? Then why it works whenever I send the commands over the monitor? Is there a more- standardized or preferred way of doing it?
Any advice is more than welcome... thanks
Hi, was not sure, looked weird, think I copied that from some example. I changed the type to int and added these conditionals:
if (isDigit(inChar) || inChar == '.' || inChar == '-') {
// convert the incoming byte to a char
// and add it to the string:
inString += (char)inChar;
Serial.print(inChar); //Serial.println(inString);
}
it's still doing the same.
Printing the chars as you suggested looks like this for manual input of 123.34: 495051465152AZ.Value:123.34
If I run the P5 sketch, I get a mess. Last value sent from processing: 165.240a Output from Arduino: 54465256AZ.Value:6.48, among other stuff.
Hello! @Delta_G: I read something about that yesterday, but cannot quite get it, how I declare an Union in processing which my "other" side and how to deal with the switching between value a for variable 1 and value b for variable 2.
@PaulS: I post the code here. I'll check out the output with spaces in a while and perhaps post again. Perhaps the mess comes from the ASCII - to- Int interpretation of the string. Do you think what I'm doing should work? I'm not certain about it, even though it seems to have no flows on manual input...
void loop()
{
while (Serial.available() > 0) {
int inChar = Serial.read();
if (isDigit(inChar) || inChar == '.' || inChar == '-') {
// convert the incoming byte to a char
// and add it to the string:
inString += (char)inChar;
Serial.print(inChar);
Serial.print(" ");
//Serial.println(inString);
}
// if you get a different char, print the string,
// then the string's value:
if (inChar == 'a') {
control = true;
azimuth = inString.toFloat();
Serial.print("AZ.Value:");
Serial.println(azimuth);
//Serial.print("2.String: ");
//Serial.println(inString);
// clear the string for new input:
inString = "";
}
if (inChar == 'b') {
control = true;
elevation = inString.toFloat();
Serial.print("EL.Value:");
Serial.println(elevation);
//Serial.print("2.String: ");
//Serial.println(inString);
// clear the string for new input:
inString = "";
}
}
}
It doesn't specifically mention floats, but the techniques there are similar to what you want. One of the examples shows a state machine which lets you receive different pieces of data in sequence.
This is pretty helpful. Thanks a lot. So my theory was right: it's a problem of speed, and I didn't know how to cope with that. I tested the code with the number delimiters '<' '>'and it was a lot better. No more strange stuff, but sometimes the numbers are printed twice in the same line. For instance
Starting ...
320
150
321
151
322322
152
...
Any Idea why should it behave like that? Can it be a sync problem with processing? I've set both at the same speed though.
I'll try the other alternatives and will post again for the record! Thanks again
The best solution for me is your "state Machine" example. Since I also need to control 3 Variables. So basically I just copied your code, tried different serial speeds and changed the names. I post it Below for the sake of others and to have everything on the same place.
Thing is, I still get this kind of corrupted outputs from Arduino:
I'm sending new values every 2 seconds from Processing, so I guess I'm not overloading anything. So why am I getting this? I'll plug the code to the motors in a while and see if at least the numbers are correct, but the output to the monitor is still confusing.
// Example state machine reading serial input
// Author: Nick Gammon
// Date: 17 December 2011
// the possible states of the state-machine
typedef enum { NONE, GOT_A, GOT_E, GOT_F } states;
// current state-machine state
states state = NONE;
// current partial number
unsigned int currentValue;
void setup ()
{
Serial.begin (57600);
state = NONE;
Serial.print ("Receiving... ");
} // end of setup
void processAzimuth (const unsigned int value)
{
// do something with Azimuth
Serial.print ("Azimuth = ");
Serial.println (value);
} // end of processAzimuth
void processElevation (const unsigned int value)
{
// do something with Elevation
Serial.print ("Elevation = ");
Serial.println (value);
} // end of processElevation
void processFire (const unsigned int value)
{
// do something with Fire
Serial.print ("Fire = ");
Serial.println (value);
state=NONE;
} // end of processFire
void handlePreviousState ()
{
switch (state)
{
case GOT_A:
processAzimuth (currentValue);
break;
case GOT_E:
processElevation (currentValue);
break;
case GOT_F:
processFire (currentValue);
break;
} // end of switch
currentValue = 0;
} // end of handlePreviousState
void processIncomingByte (const byte c)
{
if (isdigit (c))
{
currentValue *= 10;
currentValue += c - '0';
} // end of digit
else
{
// The end of the number signals a state change
handlePreviousState ();
// set the new state, if we recognize it
switch (c)
{
case 'A':
state = GOT_A;
break;
case 'E':
state = GOT_E;
break;
case 'F':
state = GOT_F;
break;
default:
state = NONE;
break;
} // end of switch on incoming byte
} // end of not digit
} // end of processIncomingByte
void loop ()
{
if (Serial.available ())
processIncomingByte (Serial.read ());
// do other stuff in loop as required
} // end of loop
Hi, The values seem to be passing ok. At least the Motors are not getting crazy anymore and they do what they should, angles seem to be allright. That means your examples helped me a lot.
But the Arduino output is thrilling because it doesn't reflect what happens with the movement...
The processing sketch is long and works on top of a couple of dependencies which need much extra information, that's why I don't post the whole thing, but the structure and the way of printing values is the following:
Library library;
float azimuth, elevation;
int fire = 0;
long previousTime = 0;
int interval = 1000;
void setup(){
library = new Library();
}
void draw(){
library.run();
azimuth=library.getAzimuth();//These are floats with up to 10 digits
elevation=library.getElevation();
int az = (long)map(azimuth, 0,360, 0,200);//Map to stepper steps
int el = (long)elevation;
long time = millis();
if (time - previousTime > interval){
port.write("A"+az);
port.write("E"+el);
port.write("F"+1);
}
}
This whole thing doesn't solve my float problem but it creates a working prototype with jumpy movement. Anyway... can a Stepper motor do something with floats? if I get a range from 20.01 Deg to 20.9 during 10 seconds, is there something that can move at such detail or close to it? I know, this is another thread but perhaps it doesn't make sense to make a big effort to achieve if it's not worth it.
int az = (long)map(azimuth, 0,360, 0,200);//Map to stepper steps
int el = (long)elevation;
What do these have to do with floats?
I suspect that some gearing of the stepper motors are going to be necessary. You have a nearly 2 degree jump each time the stepper steps (1.8 degrees, to be exact). If these motors are moving a telescope, the image is going to be very jumpy.
And, no you can't step a 1/100th of a step. Some stepper driver shields support 1/2 step, 1/4 step, or 1/8th step, but not 1/100th of a step.
The issue with the overlapping serial data is happening in how Processing is reading the replies from the Arduino, not with how it is sending the data to the Arduino. We need to see that code.
Nothing, I haven't found a solution to correctly parse the floats coming from processing, so my fastest shot was to use Nick's examples and just send integers. My purpose was to send the floats and see if a Motor could be controlled with them. But I guessed that if I just have 200 Steps, even a 360°Servo could behave better... But those are difficult to control on a step-to step basis. So I'm solving different elements here.
Here's the processing code. It will not run since the sat-tracking library hasn't been published as it is, but if it helps...:
import processing.serial.*;
import org.json.*;
import satelistica.*;
import java.util.*;
Location loc;
SatelliteGroup sats;
Predictor predictor;
PVector position;
Serial port;
String filepath = "http://celestrak.com/NORAD/elements/";
String filename = "visual";
ArrayList<Sat> passing;
float lastA = 0, lastE=0;
long interval = 500, previousTime = 0;
void setup() {
size(400,400);
smooth();
try{
loc = new Location(this, "Berlin");
sats = new SatelliteGroup(this,filepath + filename +".txt",loc);
} catch (Exception e){
sats = new SatelliteGroup(this,filepath + filename + ".txt");
}
sats.printNames();
passing = sats.getPassingSats(new Date());
port = new Serial(this, Serial.list()[0], 57600);
port.write("pos 2 serial");
}
void draw(){
Date d = new Date();
long time = millis();
if(passing.size()>0){
Sat sat = (Sat)sats.mostVisible(d);
sat.updateCoordinates(d);
position = sat.getCoordinates();
float azimuth = sat.getAzimuth(d);
float elevation = sat.getElevation(d);
println(sat.getName() +"\n"+"azimuth sat: " + azimuth + ", elev sat: " + elevation);
long az = (long)map(azimuth, 0,360, 0,720);
long el = (long)elevation;//map(azimuth, 0,90, 0,200);
//if(azimuth >180)az = 360-azimuth;
if (time - previousTime > interval){
//lastA= az;
//lastE= elevation;
port.write("A"+azimuth);
port.write("E"+elevation);
port.write("F"+1);
previousTime = time;
}
}else{println("no Sats");}
if (time - previousTime > interval*5){//Renew Sat list every 5 sec
previousTime = time;
passing = sats.getPassingSats(d);
}
}
Motors are moving a laser pointing to the position of a passing satellite so it would be a dream to make it rotate smoothly. I'm working with the Adafruit Motor shield, which supports 1/16 steps if I'm not wrong.
But, those integers can be anything. Multiply the value from getAzimuth() by 1000 and truncate to an int, rather than converting it to an integer degree and then to an integer number of steps.
Have the Arduino convert the resulting ints into something that means something, by dividing by 1000.