Hi, guys. Not long before, I needed a new serial port to communicate with Marlin Firmware, but, it seems that a new serial port like Serial1, Serial2 can not be used in any .cpp or .h files except .ino file.
You know what I am trying to tell you? Ah ha, yes, there is a way to apply a new serial port.
We just need to add a new .ino file edited in Arduino ( I debug those code in Arduino ), then add what you want the new serial port to do. Over.
I hope it can help you!
Following is my code segment:
String comdata = "";
String cmd = "";
char usart_received_char;
unsigned char state = 0;
bool Cmd_completed = false;
void cmd_execute();
/*
SerialEvent occurs whenever a new data comes in the
hardware serial RX. This routine is run between each
time loop() runs, so using delay inside loop can delay
response. Multiple bytes of data may be available.
*/
void serialEvent2() {
while (Serial2.available()) {
// get the new byte:
char inChar = (char)Serial2.read();
switch (state) {
case 0:
if (inChar == '#') state = 1;
break;
case 1:
if (inChar == '$') {
cmd = comdata;
comdata = "";
Cmd_completed = true;
cmd_excute();
state = 0;
}
else {
comdata += inChar;
}
break;
default:
break;
}
}
}
void cmd_execute() {
if ( cmd == "AskForFileList") {
Serial2.print("#TA100/230\tTB56/230\tTC110/112\tPS4\tPP56\tPT02:43:24\tFNmonkey.gco\t$");
}
if ( cmd == "GoOnPrinting1") {
;//断点打印
}
if ( cmd == "GoOnPrinting2") {
;//暂停后继续打印
}
if ( cmd == "PrintingCanceled") { }
if ( cmd == "GetInfo") { }
if ( cmd == "RefuseInfo") { }
if ( cmd == "StartPrinting") { }
if ( cmd == "PausePrinting") { }
if ( cmd == "ReplaceMaterial") { }
if ( cmd == "NozzleHeating225") { }
if ( cmd == "BedHeating225") { }
if ( cmd == "XHome") { }
if ( cmd == "YHome") { }
if ( cmd == "ZHome") { }
if ( cmd == "AllHome") { }
}
Nice trick.
A bit memory intensive, because both, the original Arduino and our Serial code will be in the program. But if you don't have to care about that - ok.
@AnHardt When I found this solution, I made no modifications in the Marlin project except adding some code segments about Serial2. And so far, Marlin firmware work well with my touchscreen.
Maybe, the disadvantages of this solution did not come out, it, however, is an alternate way to communicate with Marlin by other Ports.
@youngyhw I will be interested to use this addition soon, because I need to do an RS485 interface to a daughter-board for a project. From what I can tell about the board, it's my only option.
@youngyhw @AnHardt Is this very much required to implement a second serial port from Marlin? Because I need to implement this very thing to talk to another device asap❗
Later I may make it a feature for Marlin — RS485_SERIAL_PORT or something. But for now I just need to understand, does the above information necessarily apply?
And @youngyhw would you mind posting the .ino file — or even your whole (zipped) Marlin folder for my reference?
@thinkyhead I'm sorry, I don't know how to post the .ino file, in fact, I am a new comer in GitHub.
My .ino file is created in arduino IDE which is very easy for me to start studying Marlin.
I think adding a new .ino file in arduino IDE is not hard for you, right?
Try dropping the .ino file onto the text edit field.
"Attach files by dragging & dropping, selecting them, or pasting from the clipboard."
I think adding a new .ino file in Arduino IDE is not hard for you, right?
I just want to make sure I get the full gist of what you are describing.
@thinkyhead I know most code segments are developed in other IDE. Arduino, however, is the basic IDE. In other IDEs, .ino file maybe not the standard file format, but in arduino, it is. We should try to find some key differences between arduino IDE and other IDEs, and, I think this will benefit us all.
@thinkyhead Am I misunderstanding you?
What I am trying to do is to replace the blue-white LCD with a touch screen.
And developing a touch screen program is not just for Marlin, so I want touch screen to be a single module which communicates with other devices by usart port and power only.
Is that clear to you?
It's all clear. I'm asking to see the code, please, if possible. Because I desire very much to learn from it, and my time is short. If you can be of help, I would appreciate it a lot.
@thinkyhead
Oops, I am not in company for these days.
Look up to floor No.1, there contains the main code.
The function of serialEvent2() is receiving data from serial2 by interrupt. The data starts with '#' and ends with '$'. Then serialEvent2() is to get the command and execute according to the content of comdata.
For example, command "AskForFileList". Serial2 gets '#', serialEvent2() starts to fill comdata until serial2 gets '$', getting command succeeds, and comdata equals to "AskForFileList", and enters cmd_excute().
if ( cmd == "AskForFileList") {
Serial2.print("#TA100/230\tTB56/230\tTC110/112\tPS4\tPP56\tPT02:43:24\tFNmonkey.gco\t$");
}
will be executed.
"#TA100/230\tTB56/230\tTC110/112\tPS4\tPP56\tPT02:43:24\tFNmonkey.gco\t$" is just a test code separated by '\t'.
Then filelist will be TA100/230, TB56/230, TC110/112, PS4, PP56, PT02:43:24, FNmonkey.gco, and these names will be display on touch screen later.
Tips:
TA100/230: temperature of nozzle1 is 100, and set to 230;
TB56/230: temperature of nozzle2 is 56, and set to 230;
TC110/112: temperature of hotbed is 110, and set to 112;
PS4: printing state, 4 represents one state which can be defined by yourself, idle, pausing, printing and so on;
PP56: printing percentage, easy to understand;
PT02:43:24: printing time, being printing for 2 hours, 43 minutes and 24 seconds;
FN: file name printing, in this case, the file named monkey.gco is printing.
As the frame structure is the same, so testing frame does not match.
Later, replace TA100/230\tTB56/230\tTC110/112\tPS4\tPP56\tPT02:43:24\tFNmonkey.gco\t with the exact file names which can be got in ultralcd.cpp, function void lcd_sdcard_menu(); Of course, needs some modifications.
I don't know whether the description can make you clear, hope it can help.
Marlin.ino
@@ -32,10 +32,17 @@
*/
/* All the implementation is done in *.cpp files to get better compatibility with avr-gcc without the Arduino IDE */
/* Use this file to help the Arduino IDE find which Arduino libraries are needed and to keep documentation on GCode */
+void Serial2_begin(int boud){
+ Serial2.begin(boud);
+}
+void Serial2_println(char* s) {
+ Serial2.println(s);
+}
+
#include "Configuration.h"
#include "pins.h"
#if ENABLED(ULTRA_LCD)
#if ENABLED(LCD_I2C_TYPE_PCF8575)
Marlin.main.cpp
@@ -830,10 +830,13 @@ void servo_init() {
digitalWrite(STEPPER_RESET_PIN, LOW); // drive it down to hold in reset motor driver chips
}
void enableStepperDrivers() { pinMode(STEPPER_RESET_PIN, INPUT); } // set to input, which allows it to be pulled high by pullups
#endif
+void Serial2_begin(int boud);
+void Serial2_println(char* s);
+
/**
* Marlin entry-point: Set up before the program loop
* - Set up the kill pin, filament runout, power hold
* - Start the serial port
* - Print startup messages and diagnostics
@@ -856,10 +859,13 @@ void setup() {
// Disable JTAG on AT90USB chips to free up pins for IO
MCUCR = 0x80;
MCUCR = 0x80;
#endif
+ Serial2_begin(9600);
+ Serial2_println("Test");
+
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
setup_filrunoutpin();
#endif
setup_killpin();
Compiles. But i did no further tests.
+1240byte progmem, +195byte RAM
The trick is to use the original Arduino hardware serial before we replace it with our own.
…before we replace it…
That's the key, I guess!
What about the Arduino "standard" SoftwareSerial? Is it happy to co-exist with MarlinSerial (which I guess is the one most commonly used)?
And which pins on a RAMPS do I have left free to use as my serial RX/TX pins?
Mpff.
https://www.arduino.cc/en/Reference/Serial
The Arduino Mega has three additional serial ports: Serial1 on pins 19 (RX) and 18 (TX), Serial2 on pins 17 (RX) and 16 (TX), Serial3 on pins 15 (RX) and 14 (TX). To use these pins to communicate with your personal computer, you will need an additional USB-to-serial adaptor, as they are not connected to the Mega's USB-to-serial adaptor. To use them to communicate with an external TTL serial device, connect the TX pin to your device's RX pin, the RX to your device's TX pin, and the ground of your Mega to your device's ground.

S0 0-1 USB
S1 1 18-19 Z-min/max
S2 16-17 AUX4 used by some displays
S3 14-15 Y-min/max
Never tried SoftwareSerial together with Marlin.
AUX-1 and AUX-2 are the least used places i think.
For a custom serial I would say AUX1 seems to be the best place, you have:
5V, GND, D1, D05V, GND, D57, D58 on a nice 4-pin Dupont connector.
Would really be a nice idea if D0 D1 wouldn't be the connection to the host, used by MarlinSerial.
Due to limitations of SoftwareSerial (https://www.arduino.cc/en/Reference/SoftwareSerial) (RX needs a pin with pin change interrupt) even that is impossible.
The left 4 pins on AUX2 with RX = A9(D63) and TX = A5(D59) should be possible.
I was unaware of the PinChange interrupt limitation.. :-/
Makes sense then, on the UNO PinChange interrupt allows the usage of every pin but on MEGA only a subset.
All in all SoftwareSerial seems to be not very suitable to Marlin.
The start bit is detected by the PCI. The time difference to, and in between, the data bits are busy-waited! Interrupts seem to be off for the complete time one character comes in.
For me not promising enough to make a serious test.
:-(
Remains HardwareSerial2 on pins 16-17 on AUX-4 when not used by:
#if ENABLED(ULTRA_LCD)
#if ENABLED(REPRAPWORLD_GRAPHICAL_LCD)
#define LCD_PINS_RS 49 //CS chip select /SS chip slave select
#define LCD_PINS_ENABLE 51 //SID (MOSI)
#define LCD_PINS_D4 52 //SCK (CLK) clock
- #elif ENABLED(NEWPANEL) && ENABLED(PANEL_ONE) // where PANEL_ONE sets ULTIMAKERCONTROLLER and ULTIMAKERCONTROLLER sets NEWPANEL
+ #elif ENABLED(PANEL_ONE)
#define LCD_PINS_RS 40
#define LCD_PINS_ENABLE 42
#define LCD_PINS_D4 65
#define LCD_PINS_D5 66
#define LCD_PINS_D6 44
#define LCD_PINS_D7 64
#else
#define LCD_PINS_RS 16 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#define LCD_PINS_ENABLE 17 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#define LCD_PINS_D4 23
#define LCD_PINS_D5 25
#define LCD_PINS_D6 27
#define LCD_PINS_D7 29
#if DISABLED(NEWPANEL)
#define BEEPER_PIN 33
// Buttons are attached to a shift register
// Not wired yet
//#define SHIFT_CLK 38
//#define SHIFT_LD 42
//#define SHIFT_OUT 40
//#define SHIFT_EN 17
#endif
#endif
Means, we can use this pins when having a PANEL_ONE or REPRAPWORLD_GRAPHICAL_LCD or no display.
:-(
If having only one endstop per axis it's likely easier to shift one endstop to the other axis connector and use the freed for the new serial.
We don't know the full requirements from @thinkyhead, if he only needs Marlin -> Board communication then we could do bit banging on any pin; otherwise :+1: to your solution.
I hope to develop on a Mega2560 / RAMPS and then deploy on a MKS Gen 1.4.
I can also simply develop on a bare Mega2560 (or my spare Teensy 3).
MKS Gen 1.4 is similar enough to RAMPS 1.4 to have exactly the same problems with finding good pins.
For me hardware serial on the z-axis-endstop-connector seems to be most promising.
@Blue-Marlin Are you recommending HardwareSerial in conjunction with MarlinSerial, or just using HardwareSerial for both?
I have more data and questions and need some guidance on how to proceed…
SoftwareSerial isn't so bad??Z_MAX pins in the usual order: red 🔴 , black ⚫ , blue 🔵 . Is this all I need to get started?Z_MAX endstop only has one pin number associated with it (19).HardwareSerial for both, Mega has multiple hardware serial ports.
Scott, do you need to send a receive data from the board, or only send data to the board ?
Think about the differences. What can MarlinSerial do that HardwareSerial can't? Will you miss it?
One data pin is enough - but then you either can send or receive, depending on if you connected the Rx or Tx line of the module. I bet you need two pins.
I don't understand what you all talk about now. MarlinSerial has been occupied, but SerialPort2 not.
In my opinion, RAMPS needs some modifications in which GPIOs with certain purpose like serial ports or SPI and so on.
To make the board work better, needs not only marlin firmware, but also RAMPS board.
So, I think, we need to communicate with RAMPS board designers.
What do you say?
I bet you need two pins.
@AnHardt Seems that way.
TTL to RS485 Module
Do you think this is absolutely needed? I'm happy to do SPI or i2c or whatever else, but the board I'm trying to connect has on-board (half-duplex) RS485, so as long as I can wire an Rx and Tx I should be able to do communication. I just need to pick the best library to implement the port.
but SerialPort2 not … GPIOs with certain purpose
@youngyhw Understand that I am a beginner. I would very much like to see a working implementation of a second serial port attached to a RAMPS (or MKS Gen) board and communicating two ways with a separate board over RS485.
Do you think this is absolutely needed?
If you ask this you have not read the Wikipedia article.
In RS485 the difference between the two lines is important, not the level of the one or the other.
Like in the twisted pairs of Ethernet. That's what helps the noise resistency. Without that you could directly use TTL-RS232 half-duplex on one wire.
EDITED
you have not read the Wikipedia article
I will, soon, I swear! 🐞 I've been reading a lot of different things on this subject today.
you could directly use TTL-RS232 half-duplex on one wire
The device I'm using is very specifically all about RS485. If it were programmed cleverly (it has onboard stepper drivers and a CPU) then I could use other ways to signal it, but serial communication offers the most control, as you can send it strings of letters that act as programs.
Frankly, I think a second RAMPS would be both simpler and cheaper! This daughter-board costs over US$300.
If the device has a RS485 chip on its side you have no choice - you have to use the counterpart.
It looks like we are going to go for a simpler and cheaper option, after all, and just use a second Arduino to send the usual stepper signals to "cool muscle" P-type stepper motors with on-board drivers. The second Arduino can then manage all the Z homing logic, and probably we can get away with just connecting a few digital pins between the two boards to share state information. (I hope I'm not giving away any revolutionary proprietary information here!)
Most helpful comment
Due to limitations of SoftwareSerial (https://www.arduino.cc/en/Reference/SoftwareSerial) (RX needs a pin with pin change interrupt) even that is impossible.
The left 4 pins on AUX2 with RX = A9(D63) and TX = A5(D59) should be possible.