Serial comm. questions (no code needed, just talking out my project)

I have a personal project I have been working on over time (here and there)... and have recently started to purchase some hardware for said project.

This is your typical 'barbot' project.. (liner/slide rails stepper motors....automation of drink making)..

As I am waiting on hardware.... I started to think about the 'interface' I'd like to have for 'ordering' said drinks from a menu.

This may be better suited for a Raspberry Pi forum.. but since it does include communication with an Arduino, I figured I'd start here..

So here we go!

Being a web developer by trade.. using a Raspberry Pi with LAMP installed seemed like the most logical approach for serving up an interface to be used as the 'drink menu'

ie: There is an admin page that allows the 'user' to set the bottled name/code and order in which it exists in the barbot physical location.

This all gets saved to a table..

There is a 'menu page' where my PHP/MySQL code creates a page of drinks based on the available 'alcohol' set in the admin page (ie: if there is no vodka set to active order number or set to inactive.. no vodka based drinks will display in the menu page)...

So the web aspect of this is 85% complete... some minor CSS/style tweaks left.. and creation of the 'serial command protocol' I need to create/finalize.

And here is where the collective brain trust of members here can help me maybe streamline things.. or suggest something I may over overlooked or not accounted for.

This is a two part question/post:

  • One talks about the serial protocol I'm putting together
  • One talks about the web site being served/hosted on the RaspberryPi, and how can I get external serial data to 'trigger' change the state of the web app/interface... (example.. when a drink icon is selected.. the RPi will send that serial data out to the Arduino.. and then change the web page to display a 'drink making in progress' screen... but when the drink is complete on the Arduino side.. I want to send some sort of alert/notification that it is complete.. and to go back to showing the drink menu.

1.) The serial 'protocol'... and how it should be put together.
I have done other serial comm. based projects before.. but usually in a limited fashion (sending minor data/values).. or sending some RGB value(s) to be parsed and applied. (I'm altering this approach to hold some more data)

This is the typical start/end packet 'character' that is checked for.. then parsed once end packet has been met..etc..
Which was normally like this format:
<r=255>
(but not I am changing it up to add another value that will need to be parsed)
<b=1:1>

(I havent wrapped my brain around strtok yet on how to do the sub parsing of the x:x data)
Do I need to account for the ':' character in there? (and skip over it? like re-assign that token value twice?
ie: token3 = ':' and then re-assign token3 again after that like: char *valueToken = strtok(NULL, "\0");?

However, I'm not clear on how that works if the data/values between the starts & end packets are NOT the same length.. how does that affect the char array? (it can be less without issue.. but can not be more/longer? Is that correct?) (sorry I'm a spoiled web dev, and we dont have to worry about allocating space/resources and stuff like this.. so I always forget the process) :slight_smile:

  • What I'm also not sure about here is..if I parse the first packet.. and then execute the actions.. (ie: move stepper to position x, then dump alcohol 'x' amount of time(s)......).. am I going to loose the other incoming serial data? while the first packet 'actions' are being performed? (I dont want any packet loss/dropping where an ingredient of the drink recipe is missing/skipped obviously)

This project will need a multi-action/serial command type of approach. (per drink/recipie). (as there is no telling the ingredients or the amount.. so a set/hardcoded character count wont work here.. so I'm trying to figure out a nice way to declare: (so far)

  • action type (used to determine if this is a bottle 'shot' dump... or a valve 'pour' type of action)
  • bottle order
  • amount(s)

Here is my attempt (I'm at work.. and have no IDE to test anything as of yet) at the parsing routine:

example (projected) incoming serial data:

//example recipe format
//<b=1:1><b=2:1><m=6:200> = bottle#1/1 shot, bottle#2/1 shot, mixer#6/200ms

  • Is this flawed?
  • Can it be improved? (I have looked at other examples that use an array of delimiters, and while loops...is this a preferred approach?)
  • Should I just use the same delimiter?
  • I am again concerned about how this works.. when the next 'packet' (instruction) comes in? (ie: the next of values).. will I loose anything because I am executing the first set of actions/values?
#define SOP '<'
#define EOP '>'
bool hasStarted = false;
bool hasEnded = false;

char incomingSerialData[8];
byte index;

int positionValue = 0;
int amountValue = 0;

void setup(){
    //serial monitor output
    Serial.begin(9600);
}

//example recipie format
//<b=1:1><b=2:1><m=6:200> = bottle#1/1 shot, bottle#2/1 shot, mixer#6/200ms

void loop(){
    
    // Read all serial data available, as fast as possible
    while(Serial.available() > 0){
        char incomingCharacter = Serial.read();
        //Serial.println(incomingCharacter);
        if(incomingCharacter == SOP){
            index = 0;
            incomingSerialData[index] = '\0';
            hasStarted = true;
            hasEnded = false;
        }else if(incomingCharacter == EOP){
            hasEnded = true;
            break;
        }else{
            if(index < 8){
                incomingSerialData[index] = incomingCharacter;
                index++;
                incomingSerialData[index] = '\0';
            }
        }     
    }

    // Packet data done...parse/evaluate data
    if(hasStarted && hasEnded){

        //putstring("VALUE TOKEN: ");
        Serial.println(incomingSerialData);
        char *actionToken = strtok(incomingSerialData, "="); //split action value from location/amount values
        if(actionToken){
            //check if bottle 'action' data coming over
            if(strcmp(actionToken, "b") == 0){  
                //grab position value
                //char *positionToken = strtok(NULL, "\0");
                char *positionToken = strtok(NULL, ":");
                if(positionToken){
                    //putstring("VALUE TOKEN: ");
                    //Serial.println(positionToken);
                    positionValue = atoi(positionToken); 
                    
                    //now grab 'amount' value
                    char *amountToken = strtok(NULL, "\0");
                    if(amountToken){
                        amountValue = atoi(positionToken);
                    }
                }
            }
         
            //check if mixer action data coming over
            if(strcmp(actionToken, "m") == 0){   
                char *positionToken = strtok(NULL, ":");
                if(positionToken){
                    //putstring("VALUE TOKEN: ");
                    //Serial.println(positionToken);
                    positionValue = atoi(positionToken); 
                    
                    //now grab 'amount' value
                    char *amountToken = strtok(NULL, "\0");
                    if(amountToken){
                        amountValue = atoi(positionToken);
                    }
                }
            }           
        }

        // Reset for the next packet
        hasStarted = false;
        hasEnded = false;
        index = 0;
        incomingSerialData[index] = '\0';   
    }
}

The second (and last) part of this: (as mentioned above)

Is how to trigger the webpage 'change' on feedback/response from the Arduino (ie: once the drink is complete)

Since this will be run on the Raspberry Pi.. (which is a Linux based)... I should NOT have an issues talking over serial via PHP....correct?

I know on a Windows platform I can only use serial comm. one way (from PHP >> Arduino). but not the other way around (Arduino >> PHP)..

But on Mac/Linux..etc my understanding is that is not a problem.....correct?

If this is correct.. then the only way I can even think of doing this is to, once the 'drink is being made' message/page is displayed.. I have some sort of loop that checks for any incoming serial response? (and then output whatever I want as the new HTML/markup)..

I am NOT a fan of this 'polling' type of approach.. but in this project/case scenario.. I think its valid enough (since the project wont be doing anything/shouldnt be anything until the drink is finished being made).. but I'm open to other suggestions/approaches as well?

To be clear though.. I using Apache, PHP & MySQL as my base currently.

I don't know anything about PHP - I use Python and the Bottle web framework for all my PC based Arduino GUI development. (The name suggests it would be ideal for your project :slight_smile: )

As far as the serial comms protocol my suggestion would be to send all the data in a single message. That way the Arduino would know by the position of the item what it relates to. It also means that there is no risk of instructions getting mixed up. You could include an error-check code for additional certainty.

Have you seen Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

...R

I would structure it more like a G-code sender. G-code is commonly used in 3D printers. It contains specific commands to move to a position with coordinates in milimeters, extrude filament or whatever. Usually you want the printer moving at full speed and never waiting for a command but the small processor on the printer cannot hold an entire print in memory.

Now, I'm not advocating G-code for this example, but let's just look at how it works...

So the small processor has a buffer, say 10 commands it can hold at one time. EVERY command sent by the PC requires an acknowledgement and it won't send any more commands until the previous one is acknowledged. So, the PC sends 9 commands and gets 9 acknowledgements. The print head is now moving towards the goal set by the first command. The PC sends the 10th command. This is saved in the buffer but we cannot accept any more because the first command has not completed yet. So it doesn't send the ACK until after command 1 has completed and is removed from the buffer. The PC gets the ACK and sends command 11 and begins waiting for its ACK.

For you, I would say the buffer size is 1. The Pi cannot send any serial commands until it gets an ACK for the previous one. Maybe add a timeout: if there's no ACK in 20 seconds, assume it's done and send the next one anyway.

G-code also teaches us about which pieces of information belong on the small processor and which pieces belong on the supervisor PC. G-code always sends distances in millimeters. The small processor turns that into the required number of steps for each stepper motor. The supervisor doesn't need to know how many steps this is or even if there are stepper motors at all. The small processor doesn't know what colour plastic is loaded into extruder #1. It just gets told to extrude millimeters on that extruder. The supervisor knows what colour plastic it is, so when it needs white and it knows white is in #1, it commands extruder #1.

So for you, your interface on the Pi knows that there's gin in #1 and vodka in #2. But it doesn't have to know what type of dispenser it is. It can then send commands like "dispense 3 units of #2". The Arduino knows what kind of hardware is installed at position #2 and how to get exactly 3 units out of that hardware, without knowing what type of drink it is.

The Arduino doesn't know when the drink is complete. It just reacts to commands one at a time. The Pi knows when it has sent the last command in a recipe and got an ACK for that command, so know it knows the drink is complete. I expect the last command will be "present drink to customer and make the robot eye wink" so the Arduino would actually know that this step is different.

Another fun fact about G-code: the PC doesn't even know how big the buffer is. It just reacts to ACKs one at a time.

Hey Robin2-

Thanks for the tip/suggestion about Bottle.. (I'm going to go check it out!)
I've never written anything in Python (although its very much used for many RaspberryPi projects)

As far as your sticky/post.. yes I know I have visited it a few times over the years :slight_smile:
But I'm un-clear.. are you referencing that becuase my sample code above is erroneous? Or just pointing it out for general support/documentation on different approaches?

I was a little stumped by the strtok process on where it 'leaves' you after the first parsing of the string/input data..
so I was a little un-sure about how to handle the 'sub-parsing'.. of the x:x portion..
DO I need to account for the ':' character? parse/assign it to a variable.. but then overwrite it again to get the actual VALUE after the ':' character?

(hope that makes sense!) :slight_smile:

Sorta mentioned here: (only reference I could find..sorry)
http://forum.arduino.cc/index.php?topic=218826.msg1597113#msg1597113

Let me ask about your 'python' projects a bit.. (if you dont mind)

Were any of these web based projects? (as in serving up/hosting any sort of web page, links/buttons) to be used as an interface for the project?

I have done this using an ESP module.. (but really only for some simple 'HTML/CSS' type of GUI/interface.. where as this project is much more in-depth...and would need a database to hold the drink recipes, and admin page..etc to set the database values for the GUI...),.. and used serial communication from the ESP (web page/form data) to pass it on to a connected Arduino..... so no problem.. not only understand the process but code as well.

What I'm NOT clear on.. is the reverse communication.. sending some sort of serial response BACK to the hosted webpage (device) to have to trigger the page state/display.

Once I can actually see if this code complies and what output it gives.. I'll be better prepared to ask mire questions/tweak the code.. :wink:

http://www.cplusplus.com/reference/cstring/strtok/:
In subsequent calls, the function expects a null pointer and uses the position right after the end of the last token as the new starting location for scanning.

http://www.cplusplus.com/reference/cstring/strtok/

So the tokenized substrings won't include the token seperators.

If you've opened a Serial port to the Arduino, why would it not work in both directions? Can you test this with a very small program?

@MorganS

Thanks for the break down.. Thats just about how I understand it... (in theory)..

Couple things to clear up for me..

in your analogy..

when you refer to 'command'.. are you referring to just one 'action' like: <b=2:1>? and that only one 'command' should be sent at a time.. until the ACK has been received....correct?

I'm a little un-clear on how this works in development/reality though?

Since the user event will be just 1 interaction/action (press of an icon on touch screen or whatever).. I'm not sure how I would code this send/response routine from the RPi side of things?

Maybe easier to send the whole 'string' over? and parse it into 'steps' on the Arduino side? (although limited space/memory..etc). I suppose the same approach I was going to use for sending the whole string (PHP/POST submission..etc)..but then stay in some sort of loop to send the next piece? (still nto clear on how I get/detect the response from Arduino to RPi though?

Whew.. glad I got this discussion started now! I can start working on the hardware side of things (my first CNC/stepper type of project as well)...... and put some hardcoded buttons in place to test while developing the front end/interface.

Thanks!

All great info so far!

The commands can be as complex or as simple as you like.

move to position 1
open valve
wait 2 seconds
close valve
This recipe needs 3 shots of vodka and 2 olives and you work out which one you want to do first

I can't visualize your hardware, so I can't offer much more specific advice. The way I would think about it is go back to "What does the Pi know and what does the Arduino know?" The Pi knows which order to put the ingredients, so it should send the commands in the proper order, instead of asking the Arduino to work it out. The Pi knows what type of glass should be used for each drink but only the Arduino can detect if the actual glass it's given is the correct one.

Yes you need a loop or something that stops and waits. Even if you send the entire recipe as one string, you said you want to wait until the drink is finished. In the worst case, you just calculate how long it should take to do all those actions and use the equivalent of delay().

I'm thinking that barbots are common enough now that somebody has created an open-source g-code equivalent for them. What does Google say?

MorganS:
http://www.cplusplus.com/reference/cstring/strtok/

So the tokenized substrings won't include the token seperators.

If you've opened a Serial port to the Arduino, why would it not work in both directions? Can you test this with a very small program?

@MorganS
Im at work currently! :slight_smile: NO IDE... or anything, (BOOOOO!)
But from a past project (and I think GrumpyMike informed of this..although to be fair it was some time ago).. I was under the impression that dual communication did NOT work on Windows.. Mac/Linux yes... but not on Windows. (Using PHP that is,.. for serial communications.. only 1 way transfer)
However if it does in fact work on the Pi (Linux).. then I guess I can display a 'wait' page..... and still in a loop checking form the incoming serial data... when there display something else?

Also to touch on a comment (but its not like you know the physical/mechanical set-up,..so its really just some details on the project itself)
"But it doesn't have to know what type of dispenser it is"..
If there was ONLY bottles to be used.. or the one 'type' of dispenser.. that is correct.
I was using the 'b' parameter as a way to denote.. this will be an action where a measure 'shot' is dispensed from the target alcohol bottle..
I was then attempting to use 'm' for the mixers... (which are NOT held in a glass liquor bottle.. but in fact comes from a group of pressurized containers container the 'mixer fluids'.. (soda, orange juice...etc) controlled by some electronic values. (each with a number.... but they ALL are physically located in the same are on the 'barbot'..
So an "M" command, will always make the servo travel to the same place..
example (of how it was all working...in my head!) LOL
//<b=1:1><b=2:1><m=6:200> = bottle#1/1 shot, bottle#2/1 shot, mixer#6/200ms
<b=1:1>

  • once parsed, will tell the arduino its a 'bottle' action (so I parse the following values a specific way).. move stepper to position '1'.. and press the shot dispenser '1' times..
    <m=6:200>
  • once parsed, will tell the arduino its a 'mixer' action (so I parse the following values a specific way).. move stepper to position 'X'.. (as this is hardcoded for all "M" actions)...and opens the value for 'xxx' millis.
    Now that I have explained it a little better, is this still a flawed approach? (and why?) <-- not being snarky! LOL :slight_smile: If it is.. I want to learn WHY is not efficient, or where the trouble stems from.

** How lame am I, that I'm actually excited to work on project even more after posting all this.!!! LOL

I would try to minimise the amount of "state" that the Pi remembers. A single command should be "2 shots from bottle 1" or "200ml from mixer 1".

To make the commands more human-readable, I would use CR-LF as the seperator instead of <>. Robin uses those characters because you can see them on the screen and he doesn't have to explain to newbies that the invisible space between lines is also a character.

B1:2 //2 shots from bottle1
M2:200 //200ms from mixer 1

The colon (:slight_smile: is just for readability. Since you're unlikely to have more than 50 bottles or mixers (numbers 0-9, letters a-z and A-Z) that's not really necessary. Maybe...

Ba2 //2 shots from bottle a
Ma200 //200ms from mixer a

You could take this further by making mixers capital letters and bottles lower-case, but that is taking it too far away from readability. It must be readable so you can debug it and easily answer the question "What did it actually send?"

MorganS:
G-code also teaches us about which pieces of information belong on the small processor and which pieces belong on the supervisor PC. G-code always sends distances in millimeters. The small processor turns that into the required number of steps for each stepper motor.

I just can't understand why people don't use the greater processing power on the PC to interpret the GCode and figure out the number of steps thereby saving the Arduino from a lot of hard work.

My small CNC program just sends 4 numbers to the Arduino - the total number of microsecs for a move and the number of microsecs per step for each of the 3 motors.

Don't get me wrong - GCode is great, but IMHO it should not get as far as the Arduino.

...R

MorganS:
The commands can be as complex or as simple as you like.

move to position 1

open valve
wait 2 seconds
close valve






This recipe needs 3 shots of vodka and 2 olives and you work out which one you want to do first




I can't visualize your hardware, so I can't offer much more specific advice. The way I would think about it is go back to "What does the Pi know and what does the Arduino know?" The Pi knows which order to put the ingredients, so it should send the commands in the proper order, instead of asking the Arduino to work it out. The Pi knows what type of glass should be used for each drink but only the Arduino can detect if the actual glass it's given is the correct one.

Yes you need a loop or something that stops and waits. Even if you send the entire recipe as one string, you said you want to wait until the drink is finished. In the worst case, you just calculate how long it should take to do all those actions and use the equivalent of delay().

I'm thinking that barbots are common enough now that somebody has created an open-source g-code equivalent for them. What does Google say?

Here is the hardware/project I'm going after: (slightly different linear rail system.. but the bottles.. and the 'mixer' area (tubes to the left.. or if looking at v2... tubes in the center) is the same approach. :slight_smile:

This is NOT open source.

I did however find one that WAS open source.

I'll have to go over it a bit more in depth.. I dont want to copy much of anything.. but it will be nice to see his detailed 'instruction' and see if I overlooked anything.
Looks to be using a mobile app instead of a touchscreen.... but its gotta be pretty dang similar as far sending the instruction set(s) to the Arduino.
Understood..

After thinking and posting the above.. if the PHP two way serial comm is NOT an issue.. then I'm going to be banking/betting on that 'loop' I'll put things into after the SUBMIT (POST)...
So I can send one piece of the 'data' over.. wait for a response... send another.. wait for a response.. and when I send the last command/action and get the 'complete' response.. take myself out of the PHP (serial sending/checking) loop...and refresh the page.
So far in theory.. this works for me.
REALLY appreciate the chit-chat about this project.. helps me realize and visual things having more 'eyes' on the project.

xl97:
Let me ask about your 'python' projects a bit.. (if you dont mind)

Were any of these web based projects? (as in serving up/hosting any sort of web page, links/buttons) to be used as an interface for the project?

Sorry, I should have answered this earlier - I got distracted by GCode :slight_smile:

My projects are web-based in the sense that Bottle runs a simple webserver on my laptop and I use the browser on the same laptop to view stuff. I have come to the conclusion that HTML and CSS make the visual design very much easier than the more conventional GUI systems such as Python TKInter or Java Swing.

And when I have created the server project in this way it can also be accessed from another PC or phone with a browser that can connect to the laptop. I have used that for model train control.

What I like about Python and Bottle is that the communication with the Arduino is pure Python and completely separate from the web stuff - except that the data is shared between the "two sides of the house"

And if you follow the Bottle introductory stuff you can have a simple web page working in 5 or 10 minutes.

I think your questions about parsing have already been answered.

...R

Robin2:
Sorry, I should have answered this earlier - I got distracted by GCode :slight_smile:

HA.. no worries!
I was stuck in meetings.. and 'hand holding' some junior devs on my team.. (nothing like looking through a couple thousand lines of code to find the typo the dev did... love when you ask "well what were you working on so we can trim down where the error is stemming from?" And you get this response: "I dont know"
LMAO.. (how cant you know?.. what the heck were JUST editing?) :stuck_out_tongue:
Anyways. back on topic!
Does this Bottle web server come with the support of MySQL? (or SQL for that matter)..
What is used for a database? (if any?)
It looks nice.. I'll have to read up on it when I get home to get more in depth
For myself.. I have ZERO issues creating a the desired interface using LAMP (PHP/MySQL)... along with any all HTML/CSS/JS/jQUERY stuff that may be required.
My current issue (as I dwell on this).. is that I only have a WAMP install on my dev machine to test/develop on.

My understanding is that I there is no two way PHP serial comm. options here... So I'll have to try and set up a dev environment using a PI right away I guess.. to see if this PHP 'while loop' can do and behave the way I expect/want. (bummer)..

hmm.. maybe I can just use my MQTT Pi... (which has LAMP already installed to log my pub/sub data stuff using PHP)..

and just use the LAMP portion without any altering the MQTT stuff? (probably not!) LOL

Anyways.. thanks for all the feedback guys..

I'll chime back in once I get my hands dirty a little

Well the good news is.. the code compiled without issue..

#define SOP '<'
#define EOP '>'
bool hasStarted = false;
bool hasEnded = false;

char incomingSerialData[8];
byte index;

int positionValue = 0;
int amountValue = 0;

void setup() {
  //serial monitor output
  Serial.begin(9600);
}

//example recipie format
//<b=1:1><b=2:1><m=6:200> = bottle#1/1 shot, bottle#2/1 shot, mixer#6/200ms

void loop(){

  // Read all serial data available, as fast as possible
  while(Serial.available() > 0){
    char incomingCharacter = Serial.read();
    //Serial.println(incomingCharacter);
    if(incomingCharacter == SOP){
      index = 0;
      incomingSerialData[index] = '\0';
      hasStarted = true;
      hasEnded = false;
    }else if (incomingCharacter == EOP){
      hasEnded = true;
      break;
    }else{
      if (index < 8) {
        incomingSerialData[index] = incomingCharacter;
        index++;
        incomingSerialData[index] = '\0';
      }
    }
  }

  // Packet data done...parse/evaluate data
  if(hasStarted && hasEnded){

    Serial.print("TOTAL COMMAND PACKET (CP) CHECK: ");
    Serial.println(incomingSerialData);
    char *actionToken = strtok(incomingSerialData, "="); //split action value from location/amount values
    if(actionToken){
      Serial.print("ACTION COMMAND: ");
      Serial.println(actionToken);    
            
      //check if bottle 'action' data coming over
      if(strcmp(actionToken, "b") == 0){        
        //grab position value      
        char *positionToken = strtok(NULL, ":");
        if(positionToken){
          Serial.print("BOTTLE #: ");
          Serial.println(positionToken);
          positionValue = atoi(positionToken);

          //now grab 'amount' value
          char *amountToken = strtok(NULL, "\0");
          if(amountToken){
            Serial.print("SHOT COUNT: ");
            Serial.println(amountToken);
            amountValue = atoi(amountToken);
          }
        }
      }

      //check if mixer action data coming over
      if(strcmp(actionToken, "m") == 0){
        char *positionToken = strtok(NULL, ":");
        if(positionToken){
          Serial.print("VALVE #: ");
          Serial.println(positionToken);
          positionValue = atoi(positionToken);
          //now grab 'amount' value
          char *amountToken = strtok(NULL, "\0");
          if(amountToken){
            Serial.print("OPEN TIME: ");
            Serial.println(amountToken);
            amountValue = atoi(amountToken);
          }
        }
      }
    }
    Serial.println("");
    // Reset for the next packet
    hasStarted = false;
    hasEnded = false;
    index = 0;
    incomingSerialData[index] = '\0';
  }
}

Which gave the output of:

TOTAL COMMAND PACKET (CP) CHECK: b=1:1
ACTION COMMAND: b
BOTTLE #: 1
SHOT COUNT: 1

TOTAL COMMAND PACKET (CP) CHECK: b=2:1
ACTION COMMAND: b
BOTTLE #: 2
SHOT COUNT: 1

TOTAL COMMAND PACKET (CP) CHECK: m=6:200
ACTION COMMAND: m
VALVE #: 6
OPEN TIME: 200

So over all, I guess its a start.

Although I'm starting to see that this is more readability, than ease of parsing... like MorganS was pointing out. I'll have to think about streamlining/refining things at some point I'm sure.

Thanks for far guys.. (stepper motor stuff up next!).. :slight_smile:

xl97:
Does this Bottle web server come with the support of MySQL? (or SQL for that matter)..

No. But you can use peewee to make access to databases easy. It works with several of them. I use SQLite for my projects - the entire database is in one file. There is a nice program called SQLiteman that allows you to view your databases.

...R

May I suggest that you change your recipe protocol from this
<b=1:1><b=2:1><m=6:200>
to
<b:1:1b:2:1m:6:200>

Obviously the fine details don't matter, but what I am trying to suggest is that you have a start- and end-marker for the entire message and different markers (I have use asterisiks) for the within-message dividers.

Then when you have received the message it will be b:1:1b:2:1m:6:200 and you can parse it in two stages. First to isolate each group divided by asterisks and second to parse each group.

You will note that I am also suggesting that you use the same character (I have picked the colon) for both dividers within a group. It should make the parsing easier.

If the first two items in a group will ALWAYS be single characters the groups could be simplified from (say) m=6:200 to m6200 and you can extract the first 2 items from their character positions without any need for strtok()

I try to apply a different mindset when thinking about microprocessor programming as compared to PC programming.

...R

Hey Robin2-

Thanks for the reply..

Let me ask some questions.. :slight_smile:

1.) The suggestion on moving toward a format like: m6200 vs m=6:200

Is this for ease of parsing? less code? Why would I want to move away from strtok()? Is this just for less parsing overhead? (just trying to understand what the issues/problem the change addresses is all?)

2.) Changing the protocol..
ie:
<b=1:1><b=2:1><m=6:200>
to
<b:1:1b:2:1m:6:200>

This is something I was attempting to touch on above. With MorganS's suggestion about only sending one 'command/action' at a time.. (until an ACK/response was received to send the next action)....and not the full 'recipe'..

How does this approach fall inline with that?

The open source link I posted (I believe) does the same approach as you suggest (one big long 'string/command' being sent at once)..

However I'm not sure how I 'break it up' into steps.. waiting for the first action to be completed in the recipe..and then do another... if this is all done on the Arduino side of things? (not technically.. but in theory, I'm not sure of the approach I would need to write here)..

I need to check out his approach to see if I can understand it all..

**Thinking out loud here:

If I send thew whole command at once.. I would probably need to add some delay stuff in there...no? (instead of waiting for the 'complete ACK/response'... (since I would not really know how long it takes to move the stepper from position x to position y. (could be right next to other.. or all the way on the other side?)

xl97:
1.) The suggestion on moving toward a format like: m6200 vs m=6:200

Is this for ease of parsing? less code? Why would I want to move away from strtok()? Is this just for less parsing overhead? (just trying to understand what the issues/problem the change addresses is all?)

It would be much faster and simpler. For example you can check the command with something as simple as

char recipeText = "m6200";
recipeCommand = recipeText[0];
if (recipeCommand == 'm') {
   mixerType = recipeText[1];
   mixerTime = atoi(recipeText[2]); // not sure if this is right - but it's close
}

2.) Changing the protocol..
ie:
<b=1:1><b=2:1><m=6:200>
to
<b:1:1b:2:1m:6:200>

This is something I was attempting to touch on above. With MorganS's suggestion about only sending one 'command/action' at a time.. (until an ACK/response was received to send the next action)....and not the full 'recipe'..

How does this approach fall inline with that?

My understanding is that one piece on its own is not the complete recipe and I prefer to receive the complete recipe before starting to make any of it. If you start before you have the complete message then you run the risk that you have stuff in a glass but the recipe is never finished.

And I suspect that there isn't actually any difference between my thinking and @MorganS - I suspect his concern was to avoid parsing data as it arrives.

...R

Robin2:
It would be much faster and simpler. For example you can check the command with something as simple as

char recipeText = "m6200";

recipeCommand = recipeText[0];
if (recipeCommand == 'm') {
  mixerType = recipeText[1];
  mixerTime = atoi(recipeText[2]); // not sure if this is right - but it's close
}





...R

Hmm.. nice to see an example of the your suggested parsing method. Make sense.. (simple 'character array'.. and you can access the SINGLE character at any point...nice & simple)..
This one seems a bit suspect to me though? (but I'm not that well versed in C++)..

mixerTime = atoi(recipeText[2]);

Wouldnt that just grab the SINGLE character at index[2] though? How do you grab the remaining characters to be used as the whole number to i convert to INT?

My understanding is that one piece on its own is not the complete recipe and I prefer to receive the complete recipe before starting to make any of it. If you start before you have the complete message then you run the risk that you have stuff in a glass but the recipe is never finished.

Good point... (about it not having 'all required ingredients')

And I suspect that there isn't actually any difference between my thinking and @MorganS - I suspect his concern was to avoid parsing data as it arrives.

Hmm.. then I must be mis-understanding the proposed approach from @MorganS , as I was understanding it as.. only send that 'portion' of the recipe/action... when that sub-step is complete.. then send another....
My linear rail kit came in today.. so I'll be taking a break from the front end to assemble that and work on the stepper movement/control portion..

xl97:
This one seems a bit suspect to me though? (but I'm not that well versed in C++)..

mixerTime = atoi(recipeText[2]);

I "think" that atoi() starts at the character given to it and continues until it finds a non-digit character - in this case it will be the terminating '\0'

Good point... (about it not having 'all required ingredients')

It's more a question of not having all the instructions rather than missing ingredients. Think of reading a detective novel as far as page 297 and discovering that the final 10 pages were torn out before you got the book.

...R