0
Offline
Newbie
Karma: 0
Posts: 26
Arduino rocks
|
 |
« on: April 13, 2012, 10:12:34 am » |
I think I may have been looking at this thing too long and might be ignoring something obvious. Here is what the code below does. I have it set so when I type in a number in a text box, it sends that number to the arduino. It then parrots that number back at me. If that number is 33 it turns the led on, if its 34, it turns the led off. Whats happening, is that while the led seems t control fine, the data I am getting parroted back to me is odd. The first time I type something and hit send, my message box comes up, and displays 34 3 (if I typed in 45 it would show 45 3, 22 would show 22 3, ect). The second time I put in any number the message box show 0 0. The code is mainly just a way for me to figure out how communication works, but at this point I am stumped.
const int DirPin = 3; const int StepPin = 4;
int a = 0; int b = 0; int c = 0; int d = 0; int val = 0;
void setup(){ pinMode(DirPin, OUTPUT); pinMode(StepPin, OUTPUT); Serial.begin(9600); pinMode(8, OUTPUT); }
void loop() { if (Serial.available() > 0) { a = Serial.read();
val = a; Serial.println(val); if (val == 33) { digitalWrite (8, HIGH); } if (val == 34) { digitalWrite (8, LOW); } // if (val == 5001){ // digitalWrite (8, HIGH); // } // if (val == 5002){ // digitalWrite (8, LOW); // } } Serial.flush(); }
Dim TestVar As String
Private Sub sendDataBtn_Click(sender As System.Object, e As System.EventArgs) Handles sendDataBtn.Click TestVar = goToStepTextBox.Text
Dim btyeArr() As Byte = BitConverter.GetBytes(CInt(goToStepTextBox.Text))
If Not SerialPort1.IsOpen Then SerialPort1.Open() End If
SerialPort1.Write(btyeArr, 0, btyeArr.Length)
'SerialPort1.Close() End Sub
Private Sub SerialPort1_DataReceived(sender As Object, e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived Dim recStr As String = ""
Dim Datareceived As Boolean
Datareceived = False
While Not Datareceived
Dim recVal As Integer recVal = SerialPort1.ReadByte() If recVal = 10 Or recVal = 13 Then Datareceived = True Else recStr = recStr + Chr(recVal)
End If End While
MessageBox.Show(recStr & " " & CChar(recStr))
End Sub End Class
|
|
|
|
|
Logged
|
|
|
|
|
Miami/Florida
Offline
Full Member
Karma: 1
Posts: 167
|
 |
« Reply #1 on: April 13, 2012, 11:38:25 am » |
Try this:
I think Serial.println(); is your problem as it writes also carriage return and I don't know what else to the port. Try Serial.write();
void loop() { if (Serial.available() > 0)
{ a = Serial.read(); //No need to use (val). Serial.flush(); //Clears the buffer after reading it to have it ready for the next arriving number. Serial.write(a); //Writes the number back to the port. } if (a == 33) { digitalWrite (8, HIGH); a=0; //Clears a once its used to have it ready for the next arriving value. } if (a == 34) { digitalWrite (8, LOW); a=0; } }
|
|
|
|
|
Logged
|
|
|
|
|
Belgium
Offline
Full Member
Karma: 0
Posts: 182
|
 |
« Reply #2 on: April 13, 2012, 11:50:37 am » |
The problem is in the conversion of your textbox i think. I tried it with the serial monitor and sent 33 to it (which gets sent as 3 and 3 not 33, but whatever) and it returns what it should return. So that means the sent string/byte from the pc is wrong. I built the program you gave and put a messagebox that shows which byte it sends when pushing the button, and it sends "!", which is 33 and quote char, which is 34, so that works.. so now there's the strange thing, where's the mistake. I tried to find it, but did not succeed..
i'll try again, and if i find something i'll tell you.
edit: serial.flush() does NOT clear the buffer, it waits for every byte to be sent in the new arduino IDE @arduinoadrian: i wrote that VB code myself (and i like it to see it appearing here), and i know everything works with the receiving part if you use println(), so that's not our problem
|
|
|
|
« Last Edit: April 13, 2012, 12:04:20 pm by Steen »
|
Logged
|
|
|
|
|
Belgium
Offline
Full Member
Karma: 0
Posts: 182
|
 |
« Reply #3 on: April 13, 2012, 12:21:07 pm » |
I solved it in a way it isn't really solved, but you don't see it anymore.. if that's enough for you xs although i would lik eto see it really solved, here's the code: int a = 0;
void setup(){ Serial.begin(19200); pinMode(8, OUTPUT); }
void loop() { if (Serial.available() > 1) { a = Serial.read(); if (a > 0){ Serial.println(a); if (a == 33) { digitalWrite (8, HIGH); } if (a == 34) { digitalWrite (8, LOW); } } } }
VB: Imports System.IO.Ports
Public Class Form1 Dim TestVar As String
Private Sub sendDataBtn_Click(sender As System.Object, e As System.EventArgs) Handles sendDataBtn.Click TestVar = goToStepTextBox.Text
Dim btyeArr() As Byte = BitConverter.GetBytes(CInt(goToStepTextBox.Text))
SerialPort1.Write(btyeArr, 0, btyeArr.Length)
End Sub
Private Sub SerialPort1_DataReceived(sender As Object, e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived Dim recStr As String = ""
Dim Datareceived As Boolean
Datareceived = False
While Not Datareceived
Dim recVal As Integer recVal = SerialPort1.ReadByte() If recVal = 10 Or recVal = 13 Then Datareceived = True Else recStr = recStr + Chr(recVal) End If End While
'MessageBox.Show(recStr & " " & CChar(recStr))
If recStr.Length >= 1 And recStr <> "255" Then MsgBox(recStr) End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load With SerialPort1 .Close() .PortName = "COM3" .BaudRate = 19200 .Parity = Parity.None .DataBits = 8 .StopBits = StopBits.One .ReceivedBytesThreshold = 1 .Open() End With End Sub End Class
|
|
|
|
|
Logged
|
|
|
|
|
Miami/Florida
Offline
Full Member
Karma: 1
Posts: 167
|
 |
« Reply #4 on: April 13, 2012, 12:58:00 pm » |
I know it should work with Serial.println(), its just more complicated than using Serial.write() which I have used hundreds of times flawlessly. If you want to make it simple and extremely effective I recommend you use Serial.write(). One byte at a time and that's it. I have done it.
On the computer side using Processing its extremely simple and effective also with just this:
if(port.available()>1) {value=port.read() port.clear()} //you need to clear the port once its read to have it ready for the next value to be received.
On the Arduino side;
Serial.flush(); does indeed clears the buffer once it is executed. At least for my Project it does. I'm sending several orders to Arduino one after another that are read within the same loop and it reads them flawlessly. That means it is clearing the buffer indeed, otherwiwe there will be different results and it is working perfectly. I just gave it a little delay between sending values and another delay on the Arduino side in between readings to guarantee the values are there when I need them in the same loop. I have no question about Serial.flush(); at least with what I'm using. I downloaded the Arduino IDE maybe 5 moths ago and using Duemilanove. This is such an important instruction that I don't see why they would have changed its operation the way you are mentioning. Here there is just one byte wrttten with each write command. I don't see why it will wait until anither command to flush the buffer. One command read and it ends right there does no have to wait for any other byte on the same command. Maybe for multy byte numbers it works the way you say; but definetley not for one byte which is what is being used here (number<255).
|
|
|
|
|
Logged
|
|
|
|
|
Miami/Florida
Offline
Full Member
Karma: 1
Posts: 167
|
 |
« Reply #5 on: April 13, 2012, 01:04:15 pm » |
Sorry, it should have been:
if(port.available()>0) {value=port.read(); port.clear();} //you need to clear the port once its read to have it ready for the next value to be received.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 332
Posts: 36396
Seattle, WA USA
|
 |
« Reply #6 on: April 13, 2012, 07:35:45 pm » |
if (a == 33) { digitalWrite (8, HIGH); } if (a == 34) { digitalWrite (8, LOW); } Why do you want to go look at the ASCII table every time you add a value being sent? After looking at the ASCII table for the values 33 and 34, I guess my real question is what the f**k? Why not send something sensible, instead?
|
|
|
|
|
Logged
|
|
|
|
|
Belgium
Offline
Full Member
Karma: 0
Posts: 182
|
 |
« Reply #7 on: April 14, 2012, 05:20:03 am » |
if (a == 33) { digitalWrite (8, HIGH); } if (a == 34) { digitalWrite (8, LOW); } Why do you want to go look at the ASCII table every time you add a value being sent? After looking at the ASCII table for the values 33 and 34, I guess my real question is what the f**k? Why not send something sensible, instead? if he would be looking at the asccii table, he would do if (a == '!') { digitalWrite (8, HIGH); } if (a == '"') { digitalWrite (8, LOW); } wouldn't he? here he just reads the values back, which are numbers.. i understand that it would be easier to send something you can understand, such as L1 or L0 (from led on and led off) but that's his choice..
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 332
Posts: 36396
Seattle, WA USA
|
 |
« Reply #8 on: April 14, 2012, 07:10:06 am » |
if he would be looking at the asccii table, he would do...wouldn't he? Yes. It was the odd values in the ASCII table that caused to go hmmm. i understand that it would be easier to send something you can understand, such as L1 or L0 (from led on and led off) but that's his choice.. Or N and F, A and B, whatever, to make it easy to know what to send. 33 and 34 just do not make sense.
|
|
|
|
|
Logged
|
|
|
|
|
Miami/Florida
Offline
Full Member
Karma: 1
Posts: 167
|
 |
« Reply #9 on: April 14, 2012, 02:02:14 pm » |
"... i understand that it would be easier to send something you can understand, such as L1 or L0 (from led on and led off) but that's his choice.."
Exactly, that's his choice and as long as it makes sense for him and works fine, that's OK. Writting code is part science and part art. Maybe he just likes these numbers 33 and 34 to be sent.
"...After looking at the ASCII table for the values 33 and 34, I guess my real question is what the f**k?..."
There are nicer ways of suggesting a solution to help.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 26
Arduino rocks
|
 |
« Reply #10 on: April 14, 2012, 02:48:29 pm » |
wouldn't he? here he just reads the values back, which are numbers.. i understand that it would be easier to send something you can understand, such as L1 or L0 (from led on and led off) but that's his choice..
Thanks for everyone's response, I am going to work on this some more today. As I said before I am learning and this was mainly an example. If something like L1 is the best practice, then I will definitely do it in the future. I guess I should probably explain what my end goal is. About 2 years ago, someone threw away a nice cd changing robot. One with the printer, grabber, ect. After tearing into it, I noticed the only really bad was the control board, which I figure can be replaced by an arduino. I have already made the arm move where i want to with the stepper, and got all the sensors working, got the printer working last year. Now I need to tackle the communication with the computer. Basically I imagine most of the commands coming from the computer (i.e. go to step 100, release grabber arm) With the arduino sending events back to the computer when something happens (i.e. movement completed or sensor triggered movement stopped) That sort of thing. So I should be able to keep my commands pretty simple. Maybe use the first byte for commands, and the rest can be numbers? Once again thanks for everyone's help.
|
|
|
|
|
Logged
|
|
|
|
|
Belgium
Offline
Full Member
Karma: 0
Posts: 182
|
 |
« Reply #11 on: April 14, 2012, 02:56:01 pm » |
wow, nice ö and everything works, that's great!
well, you should do it the way you want it, but it is best to have a short string (one char) that gets sent before the number because the you know yourself what command handles which instruction. Like when you want to move the stepper arm, you can do S100 to move the stepper arm to 100. Then analyse this with the arduino, and that's it
|
|
|
|
|
Logged
|
|
|
|
|
Miami/Florida
Offline
Full Member
Karma: 1
Posts: 167
|
 |
« Reply #12 on: April 14, 2012, 03:15:36 pm » |
Interesting project. The good thing with any project is that one learns many things that can be used in next projects and they will be easier to tackle. Keep going and if you need more help post here and we will be willing to help with what we know.
I try to follow these guide lines whenever possible:
-Keep it simple. The less code and hardware the better. -Use explicative variable names, so it will be easier to understand.
Good luck.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 26
Arduino rocks
|
 |
« Reply #13 on: April 14, 2012, 06:19:00 pm » |
Taking everyone's advice I decided to change things. Got rid of the numbers and instead went with L0 and L1 like was mentioned above. Also forgetting about the visual basic stuff for now, just going to get the arduino working through the serial monitor then write the vb program. Here is the changed code.
const int DirPin = 3; const int StepPin = 4;
String a= ""; int b = 0; int c = 0; int d = 0; String val = 0;
void setup(){ pinMode(DirPin, OUTPUT); pinMode(StepPin, OUTPUT); Serial.begin(9600); pinMode(8, OUTPUT); }
void loop() {
if (Serial.available() > 0) { while (Serial.available() > 0) { //a = a + char(Serial.read()); a.concat(char(Serial.read()));
}
Serial.println(a); if (a == "L1") { digitalWrite (8, HIGH); } if (a == "L0") { digitalWrite (8, LOW); } } a = ""; Serial.flush(); }
When using the serial monitor I seem to have extra carriage returns however, and the LED does not seem to turn on. So it seems that the carriage return is getting written into the a string. I just can't figure out where. When I type L1 into the serial monitor I get: L 1 When I type L2 I get: L 2 When I type L11 I get: L 1 1 Finally When I type L1111 I get: L 1 1 11 Odd
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 332
Posts: 36396
Seattle, WA USA
|
 |
« Reply #14 on: April 14, 2012, 06:45:50 pm » |
String a= ""; String val = 0; You have a limited amount of memory on the Arduino. Using a String object to receive a 2 character input is the ultimate in laziness. Your problem is a unrealistic expectation about how serial data is transmitted. The key to understanding serial data transmission is to understand that it is sssslllloooowwww. You are expecting the serial data to arrive all at once. It does not. There may be a thousand iterations of loop between the time the L arrives and the time that the 1 arrives, when you enter L1 and press Send. Serial.flush() is almost certainly a mistake. Unless you KNOW what it is doing, and have very good reason to have it there, get rid of it.
|
|
|
|
|
Logged
|
|
|
|
|
|