Hey,
I have x64 bit OS running on one of the builds you have on the bleeding edge.
I am not sure if my setup is fully functional.... but I get it to work most often and sometimes have to kill the java process manually to get it to release the serial port....
I'm having fun with this and learning a little more each day.
My question is how can I talk to the Arduino with a direct serial connection via realterm or equivalent terminal when running the arduinoserialbare.pde on the microcontroller.
I am trying to test the interface without the myrobotlab application to halfsplit my problems, as often as they occur...
If I shut everything down, open task manager, kill process, restart mrl, then I can usually get it to resync and talk to the arduino, but I'd like to just test a command without having to do all that by sending it manually...
Any ideas?
TY
You have a really old version. . .
The real action occurs at the bottom of the bleeding edge files. There's been a lot of work going on there lately. Especially with Arduino.
When you start an Arduino service, it should display an editor with some code. That code is mrlcomm.ino, which replaces arduinobareserial. Mrlcomm.ino also reconfigures itself for any supported Arduino shield. (So far, only Adafruit Motor Shield is supported in this way.)
After setting your board and serial port, hit the compile button, and then the upload button to install mrlcomm.ino in your Arduino. Then you should be able to go to the various Arduino services, connect them and control them via the gui.
At this point, I'm not sure if the serial console can be used to control an Arduino, but that's the sort of thing that can be added if it's not already there.
There should be a new Arduino service page that goes into more detail, and some new tutorials and demos posted soon.
further to direct serial..... (not happening)
Thanks for your advice. I have updated to latest bleeding edge. Seems to not hang the com port when closing mrl.
Selfishly, I would like to use this sketch protocol to talk serially to another system as well. I wouldn't have to reflash to be able to switch between my existing system......
So I played around a little....
usbsnoopy shows mrl sending
54 out down 0x04 26.779 BULK_OR_INTERRUPT_TRANSFER aa
55 out down 0x04 26.780 BULK_OR_INTERRUPT_TRANSFER 06
56 out down 0x04 26.781 BULK_OR_INTERRUPT_TRANSFER 00
57 out down 0x04 26.782 BULK_OR_INTERRUPT_TRANSFER 09
58 out down 0x04 26.787 BULK_OR_INTERRUPT_TRANSFER aa
59 out down 0x04 26.788 BULK_OR_INTERRUPT_TRANSFER 07
60 out down 0x04 26.791 BULK_OR_INTERRUPT_TRANSFER 00
61 out down 0x04 26.805 BULK_OR_INTERRUPT_TRANSFER 00
This is just what the mrlcomm.ino shows it should be to set up a servo and then move to 0.
Seems that I better understand, which I think means that aa (10 10 bin) will be transmitted by a terminal as 61 61 hex(ascii) or 97 97 decimal
I don't think that it is possible to send the aa in a 'text' terminal window.
my test was typing AA0609 with hex display mode resulting in usb transfer of:
66 ??? down n/a 9.596 BULK_OR_INTERRUPT_TRANSFER 41 Hex for Ascii A
67 ??? down n/a 9.978 BULK_OR_INTERRUPT_TRANSFER 41
68 ??? down n/a 12.759 BULK_OR_INTERRUPT_TRANSFER 30
69 ??? down n/a 13.297 BULK_OR_INTERRUPT_TRANSFER 36
70 ??? down n/a 14.067 BULK_OR_INTERRUPT_TRANSFER 30
71 ??? down n/a 14.641 BULK_OR_INTERRUPT_TRANSFER 39
There is no way to type a character that equates to value aa in 1 keypress of a terminal window...
So sadly I will have to find some other way to switch the protocol handler in my sketch to translate for my other software. I cannot change the source of the other, only the scripting for control, not how it communicates...
I feel good that I'm starting to figure out whats happening under the hood! Really cool app, still I'm not sure of all mrl can do yet!
Thanks again!
I can tell you what the
I can tell you what the protocol is if that would help you.
MRL speaks a 4 byte command protocol to Arduino and
Arduino speaks to MRL with a 5 byte command response
If you have 2 Arduinos do you have to communicate from one to the other via serial ?
MRL has the capability of taking data from one Arduino and sending it to another MRL instance running somewhere on the internet to another Arduino (thousands of miles away ;)
If you showed us what your goal is, with big pretty pictures we might be able to assist.
Hi Grog, Thanks for the
Hi Grog,
Thanks for the breakdown.
I am a technician that works for a software company. I would like to be able to utilize my arduino to enhance my hardware interfacing capacity for my test bench. I can write scripts for and receive input from hardware and send output to meters , etc... The interface is reasonably flexible but it is serial only. I can develop variables and pass them out of the system serially, through tcp or udp, or even can bus. I have the ability to create fabulous gui's from toolkits etc... but the problem is I don't have access to the source so I can't develop the interface beyond what it is. MRLcomm.ino is way more advanced than anything I've been able to come up with (only 2 weeks with my new uno). I think that I could have used it to allow me to develop in house with my own hardware instead of having to have the production hardware exposed on my bench and risk damage. Beyond that I tinker at home and I want to set up a camera for my wife to use when I'm traveling for security outside. That's how I found your site, looking for arduino examples for servo's. I already have the camera up, serves to manycam, and splits to my motion detecting software for recording, and when I enable it to the net for outside access. I was thinking that I could use the cam stuff you've got to take the xy coordinates triggered by my existing software and move the cam to follow the target.... or allow her to move it with the tv remote....
I think you can see that I am in the learning/dreaming stage with my new arduino.
I want to thank you for what you have done with this project, its very very cool.
Glad you having fun and
Glad you having fun and dreaming up stuff. DWR & I are trying to get some helpful videos out to show some of the basics of MRL (arduino to arduino communication - remote interfacing - remote data logging - scripting Python in MRL - how to generated Python from GUI actions - and a bunch of other things I've forgotten)
Currently the Arduino service in MRL uses MRLComm.ino as a structure protocol to communicate - I've kicked around the idea of creating a more general Serial Service - which would effectively be like a serial terminal, but there has been more interest recently in getting Arduino Shields, OpenNI & OpenCV working more robustly..
Feel free to bring up any idea - MRL will assimilate !
Having Fun...!!!
Hey Grog,
I have been overseas working, and due to go back tomorrow. I haven't had much time to work on this.
I have been working on the arduino mrlcomm.ino to read a standard ascii sentence that my hope is will be translated on the arduino side to equivalent MRL data structure and be transparent to your code's operation. I have the input statement, and a checksum parameter implemented. Now I have to develop a matrix of equivalent statements, ie...
Cool Stuff
So your wrapping the MRL protocol in your own.. and you'll have a parser/router method in your Arduino code.. Is that correct?
When your talking to the arduino "directly" .. is it through the same serial port connected to the computer? Or a different serial port on the Arduino card?
What does your code do which MRLComm.ino can not? Just curious ;D
I thought in the past that it might be nice if I wrap MRLComm into a library, but have not found a good reason to at the moment.
You have an interesting project, I'd like to hear more about it... like what will the Arduino be doing... expecially when your talking to it directly?
P.S. - nice avatar Schlick .. I think your beyond grasshoppar too :D, but it looks cool
Rambling on....
Hey Grog,
So I am trying to talk to my arduino with regular ascii characters.
Your method is wonderful because it is no frills, and fast. There is no fat in your code that takes up any extra time to communicate and has a measure of data validity.
I want something that I can direct the arduino to respond when talked to serially. either I am talking to it through a terminal window or an app I write in autoit.
Your code has two problems with this.
1. untypeable characters are used to build the magic number.
2. the code is byte dependent upon position. Also not typeable.
Selfishly I want to use my arduino as a analog to digital converter when at work dealing with 'proprietary' systems. I want to use it at home as well. I only have one board right now, and I would like it to be able to just work for both without haveing to reflash. I am currently testing it with the same comm port you would use via usb. either mine direct comms or yours via MRL, just one at a time.
I can write my own programs to talk to it using your protocol because it is very fast and robust. I can program the output easily. No changes needed.
But to use it at work, I don't have access to change the source code to build an interface. But I can easily script the in/out serially to accomplish the same as my 'commercial' interfaces that are considerably more expensive and I never get to keep them for very long. So I have to rebuild my test bench constantly. If I can use the arduino, they can not tell me to build it into a customer's project.....
Also you discussed certain issues with the comm port not working.... is there problems on the host pc because of OS or Java problems. Why not just open a terminal window and tap out a sentence....
$MRTST,013,0 (\n\r)
$MRTST,013,1 (\n\r)
$MR (similar to your magic number)
TST - test ( if TST is used, checksum requirement can be ommitted)
,013 - pin assigment
,1 / ,0 - on/ off....
further, I figured to use CMD or MRL or something to indicate your code basis. and basically deliver the same format as you would use just comma seperated values.
If I decide to develop commands I could customize just by adding it into the script. just like the TST example.
Normally all input would be checksum based with is all the characters between a $ and the * to be XOR with each other. if it doesn't match its discarded....
This is all very common to serial interfaces in use for a couple decades now, GPS's use this same protocol.
(maybe I haven't used all the right words here, but the idea is there)
pretty simple....
I am not a programmer, I am interested in learning cool things, and this gives me focus on a project that helps me learn by doing.....
So I'm doing it like this....
you like?
Intriguing !
Or thought about a REST / URL protocol -> e.g. /pin/3/0
So many things to try ... so little time ;)
next project...
Hey Grog,
Rest ful ish looks very interesting...
I can't hardly digest all that is here already. I am very pleased with the DirectSerial progress so far.
But I think that your suggestion with the rest interface looks cool. I have no idea what would be required.
http code/java is a foreign language to me.
Sadly I have done no other programming projects since I took up the directserial work. Also, I want to manufacture a teensy-ish pcb smd board....
what to do now?
Congrats on your progress
Congrats on your progress Schlick,
Does it now meet all the requirements of your project?
Was curious too if you've ever used the rest of MRL (e.g. the Java part) ?
Patrick M - made a teensy smd Arduino board - he published the eagle / art I think if thats what your after..
rambling on...
Hey,
I will make an output checksum function for replies, but for now I need a break from it. too little time to work on this kind of stuff and its all I've done since I found mrl.
I have used the java interface a bit, but only for the whats this do or how does that work part of it.
I have an old laptop in the garage that is vista x64 and super slow. but I don't do much with my w7 laptop as I use that for work. so I loose patience quick on this dead slow box.
I have been super excited with the arduino because it just jumps to life....
So most of my attention is towards this end, and usually the hardware side of things. I have been playing learning a little sketchup, autoit code projects, pcb design, etc....
Initially all of this was only for the effort of making 1 camera move. I decided I needed to learn how to program a microcontroller. My prototype board was so horrible that I decided to learn how to make a pcb...
more time passes. I started working with eagle, and then sketchup(so cool). Made my first couple boards and learned how incredibly easy it was to make every rookie mistake there is...
So eventually I bought this uno, and that night I was completely amazed. two years of planning, learning, dabbling, done in one night with an arduino. Oh and then in ten minutes I found MyRobotLab and was controlling my servo with GUI. WOW. And I did'nt have to program it myself! cool.
I still cant admit defeat and must manufacture one of these little things myself just to follow through.
and I'm so damn cheap that I need to make some little boards for the little projects around the house... like the camera i wanted to move two years ago! I can't just bury this uno in a conduit box on the side of the house!
So thats my story.
oh, I can use Direct Serial just as it is for the interface I want to setup for my testbench at work.
I can directly type or program any command that MRL can do with java... and see its responce too.
This means that I can program it to my 'proprietary' interface at work for general interfacing for testing my work scripts too without having to use hardware off the 'sales' shelf. Damn salesman always sell everything, and I end up having to tear our test/production bench up all the time. with a duino, they can't sell that, its not in the pricebook and I'll be set.
I do alot of programming in autoit, mostly because its fully selfcontained once compiled. On our production environment we use mostly winxp and now having to use win7. Both out of the box with only dotnet runtimes added. I have never attempted java, mostly because I don't have the ability to update the platforms I would want to run my apps on. We need them to be dumb and bend to our will, we cannot have the environment change....
So mrl is helping me to be interested in other things, thanks for that.
-Jeff
DWR is very wise ! Use the
DWR is very wise !
Use the bleeding edge - If it's using ArduinoSerialBare it is ancient !
MRLComm.ino uses a protocol which recovers from noise on the line and other interference. It's much more robust.
Grab the Edge !
Oh, change your avatar
Oh, change your avatar picture too - you've graduated beyond scared gopher !
YAYYY!!!! working for MRL and Direct Serial.....
/**
* from 992 MRLcomm version... using an uno...
*I think we are working now.......
* upload this to your arduino, open terminal(hyperterminal) and tap out the below.
$MRTST,6,0,6,
$MRTST,6,1,9,
$MRTST,7,0,0,
$MRTST,7,0,180,
$MRTST,7,1,0,
$MRTST,7,1,180,
two servos 1 on pin6, 1 on pin7
* Edited to allow Direct Serial, MRL still works normal, Direct Serial resonds to proper
* ascii input with checksum
* paste $MRCMD,000,011,001*48 or $MRTST,0,11,1, (needs no checksum)
* TST Requires following comma to register last bit...
*
* @author greg (at) myrobotlab.org
*
* This file is part of MyRobotLab.
*
* MyRobotLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version (subject to the "Classpath" exception
* as provided in the LICENSE.txt file that accompanied this code).
*
* MyRobotLab is distributed in the hope that it will be useful or fun,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* All libraries in thirdParty bundle are subject to their own license
* requirements - please refer to http://myrobotlab.org/libraries for
* details.
*
* Enjoy !
*
* arduinoSerial
* -----------------
* Purpose: translate serial commands into Arduino language commands,
* mostly relating to IO. This would allow a computer to easily take
* advantage of Arduino's great IO capabilities, while cpu number crunching
* could be done on the computer (e.g. Video processing)
*
* Created 2 Februrary 2009
*
* http://myrobotlab.org
*
* TODO - create analogSensitivity (delta) & analogGain (scalar)
* References :
* http://www.arduino.cc/en/Reference/Constants
*
*/
#include <Servo.h>
#define DIGITAL_WRITE 0
#define DIGITAL_VALUE 1
#define ANALOG_WRITE 2
#define ANALOG_VALUE 3
#define PINMODE 4
#define PULSE_IN 5
#define SERVO_ATTACH 6
#define SERVO_WRITE 7
#define SERVO_SET_MAX_PULSE 8
#define SERVO_DETACH 9
#define SET_PWM_FREQUENCY 11
#define SET_SERVO_SPEED 12
#define ANALOG_READ_POLLING_START 13
#define ANALOG_READ_POLLING_STOP 14
#define DIGITAL_READ_POLLING_START 15
#define DIGITAL_READ_POLLING_STOP 16
#define SET_ANALOG_TRIGGER 17
#define REMOVE_ANALOG_TRIGGER 18
#define SET_DIGITAL_TRIGGER 19
#define REMOVE_DIGITAL_TRIGGER 20
#define DIGITAL_DEBOUNCE_ON 21
#define DIGITAL_DEBOUNCE_OFF 22
#define DIGITAL_TRIGGER_ONLY_ON 23
#define DIGITAL_TRIGGER_ONLY_OFF 24
#define SET_SERIAL_RATE 25
#define COMMUNICATION_RESET 252
#define SOFT_RESET 253
#define SERIAL_ERROR 254
#define NOP 255
#define MAGIC_NUMBER 170 // 10101010
// pin services
#define POLLING_MASK 1
#define TRIGGER_MASK 2
// TODO #define SERVO_SWEEP
// --VENDOR DEFINE SECTION BEGIN--
// --VENDOR DEFINE SECTION END--
// -- FIXME - modified by board type BEGIN --
#define ANALOG_PIN_COUNT 4
#define DIGITAL_PIN_COUNT 13
// -- FIXME - modified by board type END --
long debounceDelay = 50; // in ms
long lastDebounceTime[DIGITAL_PIN_COUNT];
Servo servos[MAX_SERVOS];
int servoSpeed[MAX_SERVOS]; // 0 - 100 corresponding to the 0.0 - 1.0 Servo.setSpeed - not a float at this point
int servoTargetPosition[MAX_SERVOS]; // when using a fractional speed - servo's must remember their end destination
int servoCurrentPosition[MAX_SERVOS]; // when using a fractional speed - servo's must remember their end destination
int movingServos[MAX_SERVOS]; // array of servos currently moving at some fractional speed
int movingServosCount = 0; // number of servo's currently moving at fractional speed
unsigned long loopCount = 0;
int byteCount = 0;
unsigned char newByte = 0;
unsigned char ioCommand[4]; // most io fns can cleanly be done with a 4 byte code
int readValue;
int digitalReadPin[DIGITAL_PIN_COUNT]; // array of pins to read from
int digitalReadPollingPinCount = 0; // number of pins currently reading
int lastDigitalInputValue[DIGITAL_PIN_COUNT]; // array of last input values
int digitalPinService[DIGITAL_PIN_COUNT]; // the services this pin is involved in
bool digitalTriggerOnly = false; // send data back only if its different
int analogReadPin[ANALOG_PIN_COUNT]; // array of pins to read from
int analogReadPollingPinCount = 0; // number of pins currently reading
int lastAnalogInputValue[ANALOG_PIN_COUNT]; // array of last input values
int analogPinService[ANALOG_PIN_COUNT]; // the services this pin is involved in
bool analogTriggerOnly = false; // send data back only if its different
unsigned long retULValue;
unsigned int errorCount = 0;
// MRL DirectSerial Protocol
//int newByte = 0;
int inputgroup[10] = {
0,0,0};
char inputData[300] = "";
char Checksum[3] = " ";
char Cmd[4] = " ";
int group = 0;
int group1 =0;
int stat = 0;
int cnt = 0;
int subSection[45];
char iochar[] ="";
int byteMode = 0;
const char MrlID[4] = "$MR";
int calcChecksum ;
int XOR;
int check = 0;
int ChkMatch= 0;
int stopXOR = 0;
int ValidateChecksum = 0;
char hx[5] = "0x00";
char buffer[5] = "0x00";
char ipdatabuff[5] = "0000";
unsigned char nmeaChk;
int PrintVariables = 0;
int ProceedAllowed =0;
int tstMode=0;
int Nogood = 0;
long int li1= 0;
long int li2= 0;
char *pEnd;
int ReturnMode = 0; // when return is required, use to return true or false
int Reset = 0; // when return is required, use to reset variables.
// End MRL DirectSerial definitions
void PrintVariablesList () {
if (PrintVariables == 1){ //reset variables
// variables
Serial.println("============================Variables=================================");
Serial.print("cnt");
Serial.println(cnt);
Serial.print("inputData[i]=");
Serial.println(inputData);
Serial.print("group = ");
Serial.println(group);
Serial.print("group1 =");
Serial.println(group1);
Serial.print("stat=");
Serial.println(stat);
Serial.print("check=");
Serial.println(check);
Serial.print("calcChecksum=");
Serial.println(calcChecksum);
Serial.print("Checksum[] = ");
Serial.println(Checksum);
Serial.print("hx[] = ");
Serial.println(hx);
Serial.print("nmeaChk =");
Serial.println(nmeaChk);
Serial.print("stopXOR = ");
Serial.println(stopXOR);
Serial.print("byteCount=");
Serial.println(byteCount);
Serial.print("ChkMatch= ");
Serial.println(ChkMatch);
Serial.print("ValidateChecksum = ");
Serial.println(ValidateChecksum);
Serial.print("inputgroup[]=");
Serial.println(*inputgroup);
Serial.print("byteMode =");
Serial.println(byteMode);
Serial.print("Reset = ");
Serial.println(Reset);
Serial.print("XOR= ");
Serial.println(XOR);
Serial.print("buffer[] = ");
Serial.println(buffer);
Serial.println(" Variables Print");
Serial.println("==============================================================================");
PrintVariables = 0;
}
return;
} //PrintVariables
void ResetVariables(){ //reset variables
PrintVariablesList ();
// variables
cnt=0; // Reset the buffer
for (int i=0;i<300;i++){ //
inputData[i]=' ';
}
group = 0; // Reset the group bit for next time sentence is received
group1 =0;
stat =0; // Reset the status bit for next time sentence is received
check=0;
//char hx[5] = "0x00";
//hx[5] = 0x00;
hx[0] = '\0';
hx[1] = 'x';
hx[2] = '\0';
hx[3] = '\0';
hx[4] = '\0';
char buffer[5] = "0x00";
nmeaChk = 0;
calcChecksum=0;
stopXOR = 0;
byteCount=0;
ChkMatch= 0;
ValidateChecksum = 0;
inputgroup[10]=0;
cnt=0;
//byteMode =0;
Reset = 0;
XOR= 0;
ProceedAllowed =0;
tstMode=0;
Nogood=0;
li1= 0;
li2= 0;
char MrlID[4] = "$MR";
byteCount=0;
ReturnMode=0;
Serial.println("Variables are Reset");
//softReset();
return;
} //reset variables
void setup() {
Serial.begin(57600); // connect to the serial port
softReset();
// --VENDOR SETUP BEGIN--
// --VENDOR SETUP END--
}
//
void softReset()
{
for (int i = 0; i < MAX_SERVOS - 1; ++i)
{
servoSpeed[i] = 100;
servos[i].detach();
}
for (int j = 0; j < DIGITAL_PIN_COUNT - 1; ++j)
{
pinMode(j, OUTPUT);
}
digitalReadPollingPinCount = 0;
analogReadPollingPinCount = 0;
loopCount = 0;
}
void setPWMFrequency (int address, int prescalar)
{
int clearBits = 0x07;
if (address == 0x25)
{
TCCR0B &= ~clearBits;
TCCR0B |= prescalar;
} else if (address == 0x2E)
{
TCCR1B &= ~clearBits;
TCCR1B |= prescalar;
} else if (address == 0xA1)
{
TCCR2B &= ~clearBits;
TCCR2B |= prescalar;
}
}
void removeAndShift (int array [], int& len, int removeValue)
{
int pos = -1;
if (len == 0)
{
return;
}
// find position of value
for (int i = 0; i < len; ++i)
{
if (removeValue == array[i])
{
pos = i;
break;
}
}
// if at the end just decrement size
if (pos == len - 1)
{
--len;
return;
}
// if found somewhere else shift left
if (pos < len && pos > -1)
{
for (int j = pos; j < len - 1; ++j)
{
array[j] = array[j+1];
}
--len;
}
}
/*
* getCommand - retrieves a command message
* input messages are in the following format
*
* command message - (4 byte protocol) MAGICNUMBER|FUNCTION|DATA0|DATA1
* e.g. digitalWrite (13, 1) = DIGITAL_WRITE|13|1 = 170|0|13|1
*
* return message - (5 byte protocol) MAGICNUMBER|FUNCTION|DATA0|MSB|LSB
* e.g. results of analogRead = ANALOG_READ|3|1|1 = 170|3|3|257
*
* $MRCMD,xxx,xxx*FF
* $MRCMD,000,013,001*4A
* checksum ref http://www.hhhh.org/wiml/proj/nmeaxor.html
*
*/
/*
$MRCMD,000,013,001*4A
$MRCMD,000,013,000*4B
$MRTST,000,013,000,1,2,3,4
$MRTST,6,11,0,
$MRTST,7,11,50,100,
$MRTST,0,12,0,
$MRTST,0,12,1,
*/
boolean getCommand ()
{
// handle serial data begin
if (Serial.available() > 0)
{
// read the incoming byte:
newByte = Serial.read();
if (byteCount == 0 && newByte != MAGIC_NUMBER)
{
// ERROR !!!!!
// TODO - call modulus error method - notify sender
//++errorCount;
//return false;
byteMode=1;
//++byteCount;
}
if (byteCount == 0 && newByte == MAGIC_NUMBER)
{
byteMode=0; //Ensure MRL Natural protocol
}
if (byteMode==0){ //MRL Natural
ioCommand[byteCount] = newByte;
++byteCount;
if (byteCount > 3)
{
return true;
}
else{
return false;
}
} //MRL Natural
if (byteMode==1){ //MRL Direct Serial
//
inputData[cnt] = newByte; // If there is serial port data, it is put in the buffer
cnt++;
if (newByte==13) // If the received byte is = to 13, end of transmission
{
//PrintVariables = 0;
//PrintVariablesList();
Serial.println("----------------------");
Serial.println(inputData);
Serial.println("----------------------");
//for (int ij=0;ij<3;ij++){ // Verifies if the received command starts with $MR
if (inputData[0] == MrlID[0]&& inputData[1] == MrlID[1]&&inputData[2] == MrlID[2]){
stat=3;
Serial.println("---Good------");
// Serial.println(stat);
}
else{
Nogood = 1;
Serial.println("---No Good-----");
//Serial.println(stat);
}
//}
}
//Serial.println("stat=");Serial.println(stat);
//if (Nogood = 1 && stat <3){//$MR not found
// ReturnMode = 2;
// Reset =1;
//}
if(newByte==13 && stat==3){ // If $MR, continue and process the data
//Serial.println("status stat==3");
for (int i=0;i<cnt;i++){
if (i==5){
//Serial.print("status i=="); Serial.println(i);
//Serial.print("cnt="); Serial.println(cnt);
// since $MR assume valid command incoming
Cmd[0] = inputData[i-2];
Cmd[1] = inputData[i-1];
Cmd[2] = inputData[i];
//Serial.print("Cmd:"); Serial.println(Cmd);
// sets Cmd = to buffer data position 3-5
if (Cmd[0]=='t'|Cmd[0]=='T'&&Cmd[1]=='s'|Cmd[1]=='S'&&Cmd[2]=='t'|Cmd[2]=='T'){
ValidateChecksum = 1;
stopXOR = 1;
ProceedAllowed =1;
tstMode=1;
Serial.println("No Checksum Required for Test cmd");
}//tst mode, no checksum required
else{
ValidateChecksum = 0; // checksum required
stopXOR = 0;
ProceedAllowed =0;
Serial.println("Checksum Required for CMD");
}
}
if (inputData[i]==','){ // check for the "," separator and set a group relationship to it.
//Serial.println("inputData[i]==','");
subSection[group]=i;
group++;
}
if (inputData[i]=='*'){ // check for the "*"
//Serial.println("inputData[i]=='*'");
stopXOR = 1;
subSection[group]=i; // no more commas so set last group bounds
inputgroup[group] += inputData[i];
group++;
Checksum[0] = inputData[i+1];
Checksum[1] = inputData[i+2];
Checksum[2] = 0x00;
//Serial.println("Found *");
//String BufferChecksum = char(Checksum[1]) & char(Checksum[2])
//calcChecksum ^= check;
//-----------------
//-----------------
//Serial.print("BufferChecksum=");
//Serial.print(BufferChecksum);
// Serial.print("Calculated checksum=:");
// Serial.println(calcChecksum);
}
if (inputData[i] !='*'){
//Serial.println("inputData[i] !='*'");
// still getting data
//-----------------
if (( inputData[i] != '$') && stopXOR == 0){
check ^= (inputData[i]);
//Serial.print("check=");
//Serial.print(inputData[i]);
//Serial.print("<-in : check = ");
//Serial.println(check);
//-----------------
//Reset=1;
//byteCount=0;
}
} //!='*'
//Serial.println(inputData[i]);
} // i==5 cmd group
if (ValidateChecksum == 0 && stopXOR == 1){
//Checksum compare the check (decimal) to Checksum[1] and Checksum[2]
// below structure of serial port received checksome data
//hx[1] = 0x00;
hx[2] = Checksum[0];
hx[3] = Checksum[1];
hx[1] = 'x';
hx[0] = '0';
nmeaChk = atoi(hx); //hx[2] + hx[3];
//below structure of calculated checksum xor data
sprintf(buffer,"0x%2X",check);
//Serial.print(buffer);Serial.println(hx);
//Serial.print(buffer);
//Serial.print("<- Hex calc. checksum : Serial checksum ->");
//Serial.println(hx);
PrintVariables = 1;
PrintVariablesList();
if (strcmp(buffer,hx)) { // false match
Serial.println("No Checksum Match");
ValidateChecksum = 1;
ChkMatch= 0; // 1=match 0 = no match/abort
ProceedAllowed =0;
ReturnMode = 2;
ResetVariables();
}
else{ // true match
Serial.println("Checksum's Match");
//Serial.print(buffer);
//Serial.print("<- Hex calc. checksum: Serial checksum ->");
//Serial.println(hx);
ValidateChecksum = 1;
ChkMatch= 1; // 1=match 0 = no match/abort
ProceedAllowed =1;
}
}//end checksum check required
//Serial.print("group=");Serial.println(group);
if (ValidateChecksum == 1 && ProceedAllowed ==1){ //display output
for (int ii=0;ii<10;ii++){ // Clear ioCommand[]
ioCommand[ii]=0;
iochar[ii]=0;
}
//Serial.println("--ioCommand--");
//Serial.println(ioCommand[0]);
//Serial.println(ioCommand[1]);
//Serial.println(ioCommand[2]);
//Serial.println(ioCommand[3]);
for (int i=0;i<group+1;i++){ //good data return
switch(i){
case 0 :
Serial.print("Group 1: ");
break;
case 1 :
Serial.print("Group 2: ");
break;
case 2 :
Serial.print("Group 3: ");
break;
case 3 :
Serial.print("Group 4: ");
break;
case 4 :
Serial.print("Group 5: ");
break;
case 5 :
Serial.print("Group 6: ");
break;
case 6 :
Serial.print("Group 7: ");
break;
case 7 :
Serial.print("Group 8: ");
break;
case 8 :
Serial.print("Group 9: ");
break;
case 9 :
Serial.print("Group 10: ");
break;
case 10 :
Serial.print("Group 11: ");
break;
case 11 :
Serial.print("Group 12: ");
break;
}
int q =0;
//*iochar=0x48;
li1=0;
li2=0;
//*pEnd=-1;
for (int m=subSection[i];m<(subSection[i+1]-1);m++){
//if (inputData[m+1] == '/0'){inputData[m+1] =' ';}
iochar[q]=inputData[m+1];
//Serial.print("m=");Serial.println(m);
Serial.print(inputData[m+1]);
q++;
//-----------------------------------
// How to format what I have to be useable in MRL format?....
}
iochar[q]=' ';
Serial.println("");
//-------Set ioCommand[]--------------
//long int li1;
li1=' ';
li1 =strtol (iochar,&pEnd,10);
char buffera [10]=" ";
char buffers [10]=" ";
sprintf (buffera, "%X", li1);
sprintf (buffers, "%s", buffera);
unsigned char li3 =strtol (buffera,&pEnd,16);
if (q==1&&*iochar=='0'){
li3=0;
}
if (q==0){
li3=-1;
}
ioCommand[i+1] =li3;
//Serial.print("li1=");Serial.println(li1);
//Serial.print("li3=");Serial.println(li3);
}//good data return
ReturnMode = 1;
ioCommand[0] = MAGIC_NUMBER;
} //display output
} //stat==3
if (Nogood == 1 && stat !=3){
Serial.println("Nogood ==1 and stat!=3");
ReturnMode = 2;
Reset =1;
}
if (tstMode=1 && byteCount > 300){
ReturnMode = 0;
ResetVariables();
}
if (byteMode ==1 && stat>=25){
Serial.println("byteMode ==0 && newByte ==13 && stat>=5");
++errorCount;
byteMode =0;
ReturnMode = 2;
Reset =1;
}
if (ReturnMode == 1){
// ReturnMode =0;
Serial.println("");
PrintVariables = 0;
// Serial.println("---------------");
//for (int n = 0 ;n<10;n++){
// Serial.println(inputgroup[n]);
//}
Serial.println("--ioCommand--");
Serial.println(ioCommand[0]);
Serial.println(ioCommand[1]);
Serial.println(ioCommand[2]);
Serial.println(ioCommand[3]);
Serial.println(ioCommand[4]);
Serial.println(ioCommand[5]);
Serial.println(ioCommand[6]);
ResetVariables();
Serial.println("----------------------");
return true;
}
if (ReturnMode == 2){
ReturnMode =0;
ResetVariables();
Serial.println("Return false requested!");
return false;
}
}//byteMode ==1
} // if Serial.available
//return false;
}
/*
set pollingRead = true if any of the pins are commanded to read
default behavior should be to poll read
*/
void loop () {
++loopCount;
if (getCommand())
{
/*
must comment out debugging - if serial control is used
all Serial, debugging assumes no
interference will occur due to serial
processing
*/
/*
Serial.print("c[");
Serial.print(ioCommand[0],HEX);
Serial.print("|");
Serial.print(ioCommand[1],HEX);
Serial.print("|");
Serial.print(ioCommand[2],HEX);
Serial.print("]\n");
*/
switch (ioCommand[1])
{
case DIGITAL_WRITE:
digitalWrite(ioCommand[2], ioCommand[3]);
break;
case ANALOG_WRITE:
analogWrite(ioCommand[2], ioCommand[3]);
break;
case PINMODE:
pinMode(ioCommand[2], ioCommand[3]);
break;
case PULSE_IN:
retULValue = pulseIn(ioCommand[2], ioCommand[3]);
break;
case SERVO_ATTACH:
servos[ioCommand[2]].attach(ioCommand[3]);
break;
case SERVO_WRITE:
if (servoSpeed[ioCommand[2]] == 100) // move at regular/full 100% speed
{
// move at regular/full 100% speed
// although not completely accurate
// target position & current position are
// updated immediately
servos[ioCommand[2]].write(ioCommand[3]);
servoTargetPosition[ioCommand[2]] = ioCommand[3];
servoCurrentPosition[ioCommand[2]] = ioCommand[3];
} else if (servoSpeed[ioCommand[2]] < 100 && servoSpeed[ioCommand[2]] > 0) {
// start moving a servo at fractional speed
servoTargetPosition[ioCommand[2]] = ioCommand[3];
movingServos[movingServosCount]=ioCommand[2];
++movingServosCount;
} else {
// NOP - 0 speed - don't move
}
break;
case SET_SERVO_SPEED:
// setting the speed of a servo
servoSpeed[ioCommand[2]]=ioCommand[3];
break;
case SERVO_SET_MAX_PULSE:
//servos[ioCommand[2]].setMaximumPulse(ioCommand[3]); TODO - lame fix hardware
break;
case SERVO_DETACH:
servos[ioCommand[2]].detach();
break;
case SET_PWM_FREQUENCY:
setPWMFrequency (ioCommand[2], ioCommand[3]);
break;
case ANALOG_READ_POLLING_START:
analogReadPin[analogReadPollingPinCount] = ioCommand[2]; // put on polling read list
analogPinService[ioCommand[2]] |= POLLING_MASK;
// TODO - if POLLING ALREADY DON'T RE-ADD - MAKE RE-ENTRANT - if already set don't increment
++analogReadPollingPinCount;
break;
case ANALOG_READ_POLLING_STOP:
// TODO - MAKE RE-ENRANT
removeAndShift(analogReadPin, analogReadPollingPinCount, ioCommand[2]);
analogPinService[ioCommand[2]] &= ~POLLING_MASK;
break;
case DIGITAL_READ_POLLING_START:
// TODO - MAKE RE-ENRANT
digitalReadPin[digitalReadPollingPinCount] = ioCommand[2]; // put on polling read list
++digitalReadPollingPinCount;
break;
case DIGITAL_READ_POLLING_STOP:
// TODO - MAKE RE-ENRANT
removeAndShift(digitalReadPin, digitalReadPollingPinCount, ioCommand[2]);
digitalPinService[ioCommand[2]] &= ~POLLING_MASK;
break;
case SET_ANALOG_TRIGGER:
// TODO - if POLLING ALREADY DON'T RE-ADD - MAKE RE-ENTRANT
analogReadPin[analogReadPollingPinCount] = ioCommand[2]; // put on polling read list
analogPinService[ioCommand[2]] |= TRIGGER_MASK;
++analogReadPollingPinCount;
break;
case DIGITAL_DEBOUNCE_ON:
debounceDelay = 50;
break;
case DIGITAL_DEBOUNCE_OFF:
debounceDelay = 0;
break;
case DIGITAL_TRIGGER_ONLY_ON:
digitalTriggerOnly = true;
break;
case DIGITAL_TRIGGER_ONLY_OFF:
digitalTriggerOnly = false;
break;
case SET_SERIAL_RATE:
Serial.end();
delay(500);
Serial.begin(ioCommand[2]);
break;
case SOFT_RESET:
softReset();
break;
// --VENDOR CODE BEGIN--
// --VENDOR CODE END--
case NOP:
// No Operation
break;
default:
// Serial.print("unknown command!\n");
break;
}
// reset buffer
ioCommand[0] = -1; // MAGIC_NUMBER
ioCommand[1] = -1; // FUNCTION
ioCommand[2] = -1; // PARAM 1
ioCommand[3] = -1; // PARAM 2
byteCount = 0;
} // if getCommand()
// digital polling read - send data for pins which are currently in INPUT mode only AND whose state has changed
for (int i = 0; i < digitalReadPollingPinCount; ++i)
{
if (debounceDelay)
{
if (millis() - lastDebounceTime[digitalReadPin[i]] < debounceDelay)
{
continue;
}
}
// read the pin
readValue = digitalRead(digitalReadPin[i]);
// if my value is different from last time && config - send it
if (lastDigitalInputValue[digitalReadPin[i]] != readValue || !digitalTriggerOnly)
if (lastDigitalInputValue[digitalReadPin[i]] != readValue || !digitalTriggerOnly)
{if (byteMode==0){ //MRL protocol
Serial.write(MAGIC_NUMBER);
Serial.write(DIGITAL_VALUE);
Serial.write(digitalReadPin[i]);// Pin#
Serial.write(readValue >> 8); // MSB
Serial.write(readValue); // LSB
}else{ //DirectSerial
Serial.print(MAGIC_NUMBER);
Serial.print("|");
Serial.print(DIGITAL_VALUE);
Serial.print("|");
Serial.print(digitalReadPin[i]);// Pin#
Serial.print("|");
Serial.print(readValue >> 8); // MSB
Serial.print("_");
Serial.println(readValue); // LSB
}
lastDebounceTime[digitalReadPin[i]] = millis();
}
// set the last input value of this pin
lastDigitalInputValue[digitalReadPin[i]] = readValue;
}
// analog polling read - send data for pins which are currently in INPUT mode only AND whose state has changed
for (int i = 0; i < analogReadPollingPinCount; ++i)
{
// read the pin
readValue = analogRead(analogReadPin[i]);
// if my value is different from last time - send it
if (lastAnalogInputValue[analogReadPin[i]] != readValue || !analogTriggerOnly) //TODO - SEND_DELTA_MIN_DIFF
{if (byteMode==0){ //MRL protocol
Serial.write(MAGIC_NUMBER);
Serial.write(ANALOG_VALUE);
Serial.write(analogReadPin[i]);
Serial.write(readValue >> 8); // MSB
Serial.write(readValue & 0xFF); // LSB
}else{ //DirectSerial
Serial.print(MAGIC_NUMBER);
Serial.print("|");
Serial.print(ANALOG_VALUE);
Serial.print("|");
Serial.print(analogReadPin[i]);
Serial.print("|");
Serial.print(readValue >> 8); // MSB
Serial.print("_");
Serial.println(readValue & 0xFF); // LSB
}
}
// set the last input value of this pin
lastAnalogInputValue[analogReadPin[i]] = readValue;
}
// handle the servos going at fractional speed
for (int i = 0; i < movingServosCount; ++i)
{
int servoIndex = movingServos[i];
int speed = servoSpeed[servoIndex];
if (servoCurrentPosition[servoIndex] != servoTargetPosition[servoIndex])
{
// caclulate the appropriate modulus to drive
// the servo to the next position
// TODO - check for speed > 0 && speed < 100 - send ERROR back?
int speedModulus = (100 - speed) * 10;
if (loopCount % speedModulus == 0)
{
int increment = (servoCurrentPosition[servoIndex]<servoTargetPosition[servoIndex])?1:-1;
// move the servo an increment
servos[servoIndex].write(servoCurrentPosition[servoIndex] + increment);
servoCurrentPosition[servoIndex] = servoCurrentPosition[servoIndex] + increment;
}
} else {
removeAndShift(movingServos, movingServosCount, servoIndex);
}
}
} // loop
Hi Schlick, Nice to see ya
Hi Schlick,
Nice to see ya again.
I looked at your update a litte. Your out of sync, MRLComm.ino has changed - (we move fast here :)
I think a XOR checksum is a good idea...
Would a RESTful (ish) protocol work for your requirements?
to write pin 13 LOW
/pin/13/0
to write pin 13 HIGH
/pin/13/1
to read pin 13
/pin/13
If a protocol adapter like this was put into place - would it satisfy your problems?
thoughts....
Hey Grog,
I was able to checksum match, thats now working today! yay!
I am closer with my concept. Here is what I like about what I am trying to do.
I am presenting another alternative to your natural input. either is sufficient, and either all the time.
Your protocol is faster, no doubt, don't remove it, it's perfect....
Ascii based input is slower by nature because it requires more bytes to be transmitted to accomplish the same.
I am (in progress/attempting) to convert to the native code inside the arduino so your original MRLcomm is still intact.
the matrix that you are using is all that is needed, and if txt names are desired, they can easily be declared for use.
$MR start of valid cmd sentence... consider it magicnumber 170
XXX, command also iocommand[1]. if cmd is TST then checksum requirement will be disabled.
XXX,XXX parameters , iocommand[2] &[3]
, XXX,XXX,XXX,XXX so far extra parameters are available, not yet defined
*XX Checksum (Hex XOR everything between $ and *)
I will pursue this, because it is a standard type serial interface....
... not saying what you are suggesting is not better......
Still learning, slowly...
Thanks for the help yesterday
Jeff