GRBL + LCDKeypad Shield

Scenario:
I'm in the midst of building a cheap CNC project. Currently i have GRBL 0.9 on an funduino uno, and 3x easydriver stepper controllers.

What i'm attempting to do, is use a sainsmart arduino mega 2560 r3 as a secondary terminal to access grbl functions.

My thinking was that i could connect the uno to the PC via USB, and connect the mega to the UNO via RX/TX pins

Where i seem to be having difficulty:

I was hoping that i could use software serial to "spy" on the uno's serial activity with the PC, and split off pertinent information such as axis positions etc, and print that to the LCD.

I was also hoping to have a menu on the LCD with basic functions, such as pause/resume, manual jogging on each axis for positioning, homing, software restarting grbl, and sending the unlock command.

The menu part i have figured out, and receiving on the RX line appears to work partially.

However, when i try this setup, GRBL stops responding on the PC connection (GRBL Control).

I also seem to be having another issue, that may be related to the first one, whenever i stream the serial data to the LCD, there are quite a bit of garbage characters being displayed.

My questions are thus:

  1. Is it possible to use software serial to "spy" on the GRBL serial communications (as i read somewhere the USB and the RX/TX lines on the uno share the same UART) without interrupting, or otherwise causing issues with PC-USB -> Arduino communication

  2. Is it possible to interject commands from the second arduino to the first one without causing issues.
    i.e. is there some sort of interrupt i need to wait for within the serial communication before injecting my own commands from the LCD menu?

  3. Has someone already done this? If i'm reinventing the wheel, does someone know of a working example of this setup that i could peruse and learn from.

Hardware Information Links:
EasyDriver 4.4 Stepper Motor Breakout Modules
LCD Keypad Shield
Funduino Uno R3
Sainsmart Mega2560 R3

Current testing codes:

Software serial to LCD test (Garbage output to screen, GRBL stops responding)

#include <LiquidCrystal.h>
#include <SoftwareSerial.h>

#define rxPin 50 // receive
#define txPin 48 // transmit

SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);


void setup(){
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
   // define pin modes for tx, rx, led pins:
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);
 
  mySerial.begin(115200);
  //mySerial.print("LCD Display...");
  lcd.print("Initializing...");
  delay(800);
  lcd.clear();
  lcd.print("Ready");
}

void loop()
{
  // when characters arrive over the serial port...
  if (mySerial.available()) {
    // wait a bit for the entire message to arrive
    delay(100);
       
    // clear the screen
    lcd.clear();
    // read all the available characters
    int index = 0;

    while (mySerial.available() > 0) {

      // display each character to the LCD
      if(index < 16){
     
          lcd.setCursor(index, 0);   
     
      }else{     
         if(index > 34){
           index = 0;
           
           lcd.setCursor(index, 0);
         }else{
           lcd.setCursor(index-16, 1);
         }
      }
     
      lcd.write(mySerial.read());
      delay(100);
      index++;
    }
   
   }
}

LCD Menu test (still needs loads of work :smiley: )

#include <LiquidCrystal.h>
//Software serial disabled until i figure it all out
//#include <SoftwareSerial.h>

//#define rxPin 50 // receive
//#define txPin 48 // transmit

//SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

// Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

//States for the menu.
int currentMenuItem = 0;
int lastState = 0;

void setup() {
     // define pin modes for tx, rx, led pins:
//  pinMode(rxPin, INPUT);
//  pinMode(txPin, OUTPUT);
 
//  mySerial.begin(115200);

   //Set the characters and column numbers.
   lcd.begin(16, 2);
   //Print default title.
   clearPrintTitle();
}

void loop() {
  //Call the main menu.
  mainMenu();
}

void mainMenu() {
  //State = 0 every loop cycle.
  int state = 0;
  //Refresh the button pressed.
  int x = analogRead (0);
  //Set the Row 0, Col 0 position.
  lcd.setCursor(0,0);

  //Check analog values from LCD Keypad Shield
  if (x < 100) {
    //Right
  } else if (x < 200) {
   //Up
    state = 1;
  } else if (x < 400){
   //Down
    state = 2;
  } else if (x < 600){
    //Left
  } else if (x < 800){
    //Select
    state = 3;
  }

  //If we are out of bounds on the menu then reset it.
  if (currentMenuItem < 0 || currentMenuItem > 5) {
   currentMenuItem = 0; 
  }

  
   //If we have changed Index, saves re-draws.
   if (state != lastState) {
      if (state == 1) {
         //If Up
          currentMenuItem = currentMenuItem - 1; 
          displayMenu(currentMenuItem);
      } else if (state == 2) {
         //If Down
          currentMenuItem = currentMenuItem + 1;  
          displayMenu(currentMenuItem);
      } else if (state == 3) {
         //If Selected
         selectMenu(currentMenuItem); 
      }
      //Save the last State to compare.
      lastState = state;
   } 
   //Small delay
  delay(5);
}                

//Display Menu Option based on Index.
void displayMenu(int x) {
     switch (x) {
      case 1:
        clearPrintTitle();
        lcd.print ("-> Reset GRBL");
        break;
      case 2:
        clearPrintTitle();
        lcd.print ("-> Zero Position");
        break;
       case 3:
        clearPrintTitle();
        lcd.print ("-> Home ");
        break;
      case 4:
        clearPrintTitle();
        lcd.print ("-> Pause Job");
        break;
      case 5:
        clearPrintTitle();
        lcd.print ("-> Resume Job");
        break;
    }
}

//Print a basic header on Row 1.
void clearPrintTitle() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Sinful Media CNC ");
  lcd.setCursor(0,1); 
}

//Show the selection on Screen.
void selectMenu(int x) {
   switch (x) {
      case 1:
        clearPrintTitle();
        lcd.print ("GRBL Resetting...");
        delay(2500);
        clearPrintTitle();
        displayMenu(currentMenuItem);
        //Send command to GRBL to software reset
        break;
      case 2:
        clearPrintTitle();
        lcd.print ("Zeroing POS...");
        delay(2500);
        clearPrintTitle();
        displayMenu(currentMenuItem);
        //Send command to GRBL to zero position
        break;
       case 3:
        clearPrintTitle();
        lcd.print ("Homing...");
        delay(2500);
        clearPrintTitle();
        displayMenu(currentMenuItem);
        //Send command to grbl to go home
        break;
      case 4:
        clearPrintTitle();
        lcd.print ("Pausing...");
        delay(2500);
        clearPrintTitle();
        displayMenu(currentMenuItem);
        //Send command to GRBL to Pause Job Queue
        break;
      case 5:
        clearPrintTitle();
        lcd.print ("Resuming...");
        delay(2500);
        clearPrintTitle();
        displayMenu(currentMenuItem);
        //Send command to GRBL to Resume Job Queue
        break;
    }
}

ArcAiN6:
Scenario:
I'm in the midst of building a cheap CNC project. Currently i have GRBL 0.9 on an funduino uno, and 3x easydriver stepper controllers.

What i'm attempting to do, is use a sainsmart arduino mega 2560 r3 as a secondary terminal to access grbl functions.

My thinking was that i could connect the uno to the PC via USB, and connect the mega to the UNO via RX/TX pins

Nope, the UNO -> PC link uses the RX/TX pins (0,1) so either use them as Serial Monitor(on PC) or spying on the commands from the PC to the GRBL. You can tie the RX pin (0) into either Rx or TX of the Mega, depending on which you choose you will see either the command stream or the response stream. Now the TX pin is tricker. you cannot have two TX's talking to one RX. so you have to isolate the TX's from each other one way that works is with two diodes and one resistor like this:

Since Serial is Idle at 5V each TX can pull the RX line LOW, and the Resistor pulls it high.

chuck.

Thank you Chucktodd,
I was wondering if another approach be possible.

i.e. Connect the mega with LCD Keypad shield to the PC, then use one of the extra rx/tx sets to send commands to the UNO. Basically using the mega between the PC and UNO to parse information and pass commands either from the PC to the UNO, or from the LCDMenu on mega to the UNO.

So the work flow would be pc communicates to mega, mega sends the PC commands directly to the UNO , uno then sends information to mega, mega sends a copy to the PC, and processes a copy to print to LCD

so basically,
PC -> MEGA,
Mega TX2 -> Uno RX
Uno TX -> MEGA RX2

I ask, because i don't readily have the hardware for your circuit, and where i live, shipping is a nightmare.

It strikes me that it would make much more sense to connect the Mega to the PC and use it to transmit relevant data to the Uno using one of its extra serial ports.

...R
I guess you got to the same place while I was typing.

I guess so robin...

Now all i have to do is figure out how to do it lol

So running, (or crawling as my coding skills a minimal at best) I came up with this.

Perhaps someone can look it over and let me know if i've done something derpy with it.

Also, i've not figured out how to collect the data from the UNO serial, and make it look clean and presentable on the LCD.

I also need to figure out how to create a sort of timeout on menu, that way it reverts to just showing information on the LCD, and whenever someone pushes a button, it rolls back into the menu..

What i'de like to display on the LCD is the X/Y/Z coordinates, and Feed Rate.

Here's the code i've cobbled together:

Attached is my ino as the 9000 character limit won't allow me to post it in code-block.

LCDKeypadMenuTemplate2.ino (8.19 KB)

I have just had a quick look at your program.

My first impression is that what you want to do is moderately complex and will need better organized code. Think about having code in loop() that is like this

void loop() {
   receiveFromPC();
   receiveFromUno();
   upDateLCD();
   processPCData();
   sendToUno();
   sendToPC();
}

and each of the functions deals with one aspect of the project. You can develop each function separately in a short program.

To get you started one or other the examples in serial input basics would probably be suitable for the two receivexxx() functions.

And have a look at planning and implementing a program.

...R

Thank you robin, i suppose the reason i have been putting things together the way i have is i'm not sure how the loop works..

I.e. if i have several as you suggest, does it loop all of those constantly, or each one sequentially in order of appearance?

If it runs sequentially, how would i keep from resetting the menu during operation by user, or worse, cutting off the data stream from the serial mid-read/transmit if a loop changes over during these operaitons.

If they all run constantly, how would i go about making sure that any sort of "timeout" mechanism i put in place to revert from an inactive menu to displaying position information on the LCD doesn't get interrupted.

I guess it's really down to my lack of understanding where it comes to how the code is run. Is it a linear execution, or do all things called in void loop run constantly.

I've only been at this a few weeks, so i'm still very wet behind the ears as far as my understanding of alot of this.

But i am learning as i go :slight_smile:

Reading your suggested topics now :slight_smile:

I.e. if i have several as you suggest, does it loop all of those constantly, or each one sequentially in order of appearance?

Until you learn the terminology, we can't communicate. Start with NOT using pronouns when you don't know what they refer to.

Several what? You can't have several loop() functions. You can have ONE. That makes the rest of your question nonsense.

Thank you for the elitist comment PaulS. I'll be sure not to post any questions directed at Robin2 in your presence again.

Perhaps in time, with guidance, and assistance from the community, i will learn enough about the subject that we can both be condescending to new users together. That way we eliminate the urge for users to post questions seeking advice, guidance and assistance during their journey through learning, and discovery.

Some people don't like @Paul_S's style but it is usually worth putting the dislike to one side and noting the underlying message. Words that make sense when used in speech (where intonation, facial expressions and body language are also available) can be ambiguous when used in writing.

I.e. if i have several as you suggest, does it loop all of those constantly, or each one sequentially in order of appearance?

If it runs sequentially, how would i keep from resetting the menu during operation by user, or worse, cutting off the data stream from the serial mid-read/transmit if a loop changes over during these operaitons.

It works through each function sequentially in order. Usually the order of the functions does not matter because each one gets attention every few millisecs, or quicker.

The trick (which is not complicated) is to write the functions so that they work in that environment.

...R

Thank you very much robin. I've already started to separate tasks into functions like you suggested. I do see the advantage of doing that. The smaller parts are making things easier to understand, and tinker with.

Well. Thank you very much Robin2, your helpful suggestions have helped me to finally get it working :slight_smile:

For anyone else interested, you can find the arduino project files i used to do this attached below.

For a quick note of what it does:

This uses a Mega with an LCD Keypad shield as layer between an arduino running GRBL.

I did this, because XLCD was the only project i found that does this, or something similar, but it uses a module that the user must make, and is for LCD only, no keypad, as well as the only way i could get it to verify, or compile for upload was to use outdated and specialized libraries, and an older version of the Arduino IDE.

What it does:

  1. Serial data sent to the mega is passed onto the arduino running GRBL. This way you can use your PC software the control the unit.

  2. Because you usually want to keep your PC away from dust, moisture, and metal chips, you can use this to control common features used on GRBL, and still keep your PC a safe distance away from the actual CNC machine, or, just use this as a quick means to do common tasks, without having to type a bunch of commands into serial interface.

  3. The only library included in the ino is the LiquidCrystal Library. No hunting down outdated, or difficult to find revisions of libraries.

As i hammer away at this, and get new hardware in (china post is SLOOOOOW) such as SD Card reader, I2C module for the LCD, and a 4x4 keypad, i'll try to add them, as well as a "configure" tab so you can do all your configuration in one tab, then go.

I still need to work out capturing the serial data to a temporary buffer so that it can be split up, and used to display important information, such as X, Y, Z position, as well as Idle/Working/Alarm states of GRBL.

Anyone can feel free to use this, include it, expand upon it, but i request that any further development of it, please share with the rest of the community, as there don't appear to be too many options for people where this particular niche is concerned.

LCDKeypadMenuTemplate2.zip (3.83 KB)

ArcAiN6:
(china post is SLOOOOOW)

That's specially to discourage you from destroying your local economy.

How much will Chinese things cost when Chinese wages are the the same as US and European wages but neither Europe nor USA has the capability to build the components ?

...R

Of coarse we have the capability.
i bought an I2C module, the 4x4 membrane keypad, SD Card module, and a 1000 1/4w resistors for $1 or less each.

Yes, there is an issue with the wage difference, but mainly, the cost of products in the US and EU has less to do with the wage difference, and more the do with corporate greed.

For an example, we can look at a hip replacement (my aunt just had one, so i looked up the figures)

It costs on average about $358 to manufacture a hip replacement. The device is then sold to hospitals for roughly $8000 - $12,000, then it sold to the patient for $20,000 - $35,000.

The same can be said of most of the things sold by large corporations. The wage issue really has less to do with the price of a thing, than the greed of shareholders, and corporate ceo's.

I will agree that wages do play a part in pricing to a small degree, but the main reason pricing is so different has to do with the profit margin goals being set by the corporation. Wages usually only represent pennies in the total cost when you are talking about mass production.

ArcAiN6:
I will agree that wages do play a part in pricing to a small degree, but the main reason pricing is so different has to do with the profit margin goals being set by the corporation. Wages usually only represent pennies in the total cost when you are talking about mass production.

Sorry, I just used "wages" as a catch-all for all of the things you mention. And I share your annoyance about coporate greed. Unfortunately most people expose the same attitude whenever they get a chance - hence the preference for cheap foreign goods at the expense of local employment. And look how wveryone abandoned the mom and pop stores in favour of huge supermarkets. Then they need wasteful cars to get to the stores rather than being able to walk - which would also be better for their health [/rant]

Of coaurse we have the capability.

But it won't stay indefinitely if the products are being bought from Chinese factories.

And don't expect the Chinese to be any less greedy than their western counterparts. They are just waiting for the opportuinity.

...R

i have tryed to do this using your sketch but so far didnt get to work, i have conected pc to arduino mega with a 20x4 LCD Display Module HD44780 then from mega tx1 to rx1 conected to the rx and tx on the cnc shield v3 with arduino uno and grbl, when i open grbl software it detects the port, but when i send information to run motors dont run, gets stuck not sure what i did wrong or if isnt working cause im not using a LCDKeypad Shield or if some conection wrong, i tried used the rx2 and tx2 on the mega but it dont recognizes the port, tx1 and rx1 recognizes, just dont makes the motors move

Hi,

I have the same problem as @meph328 !

I want use your sketch (code) with an Arduino Uno + CNC Shield v3 + Arduino Mega2560 + 20x4 LCD (or 128x64 GLCD) but without "Keypad shield".

Could you help us, with indications to convert & transform your code (sketch) by replacing the "Keypad shield" with this type of keypad ( This keypad or this keypad)!

I'm newbie, and i really want use this sketch for my CNC Project, please help me !

Thanks in advance :wink:

I want use your sketch (code)

Who's code?

I'm newbie, and i really want use this sketch for my CNC Project

Newbie and CNC project do NOT belong in the same sentence.