loading
What great fun the Arduino is but...

The IDE serial monitor just isn’t sophisticated enough for my liking. I found it difficult to get a mass of information displayed meaningfully. The monitor whizzed past and intermixing different types of information just made the display a muddle of text.

I tried Processing for outputting my IMU which was very informative but was prettier than I needed and I found myself struggling to add more output information especially when I wanted it to be running concurrently.

So I wrote my own serial monitor and if there is enough interest I will also look into making it available.
I can’t really show you all the code as there is masses of it but I will provide some hints and tips for anybody who wants to have a go themselves.

It’s been tested on an Arduino UNO, Mega256, Nano and Pro Mini (all clones) and also on self builds using the ATMega328 with a CP2102 for the USB serial connection.

This was developed under .NET for the Windows platform and has the following forms/visualisers:
  • Main monitor
  • Message sender
  • Trace copy
  • LCD emulator
  • Freeform drawing surface
  • Alert reporter with  ability to run external programs
  • PS3 controller visualiser
  • XY scatter plotter
  • Sweep plotter
  • Histogram plotter
  • IMU visualiser
These can be controlled and configured from the PC and/or from the Arduino. To make the above forms respond to the data stream a simple protocol is used with commands identified with a # prefix and parameters separated by a ~ character. Free text is supported for viewing in the main monitor. All window forms have a quick button back to the main monitor window, a clear/reset button, a pause option, tracer text for that particular window form and a test button to try out commands directly as if sent via the serial port.

I adopted text representations rather than binary so it is possible to ‘see’ what is going on in the Arduino IDE’s serial monitor which aids development speed. It may not be as compact or fast as binary (which could be made more data efficient) but its convenience outweighs this benefit and the typical PC is well able to cope - it is possible to have all of the above forms being updated simultaneously from an Arduino running 19200 baud.

This can be used for other serial sources than the Arduino should it be needed to.

Planned enhancements include:-
  • A scripting tool so that messages can be sent to the Arduino based on the content of a script file stored on the PC.
  • User defined visualisers. These will be constructed from definition files that allow custom forms to be built up from standard components such as buttons, sliders, graphing tools so it can receive and send data to the Arduino.
  • Data out formatted for use in third party systems include Microsoft Excel, XML, CSV and so on.
  • Custom visualiser for tuning common subsystems such as PID (proportional, integral and derivative) controllers and IMU filtering.

Step 1: Main Monitor Window

Main monitor window 
 
  • This allows selecting, refreshing, opening and closing the COM port.
  • Choosing a reading strategy - fast read normally and one line at a time where more control over the sequencing of messages to and from is important.
  • Control the display - pausing, clearing and copying the trace, adding in a timestamp which also shows whether the data flow is inbound, outbound or looped back (for test purposes where the serial device does not need to be connected).
  • Choosing a display refresh rate to optimise the loading on the PC when large quantities of data are being transmitted. Whilst reading the trace at high speed is difficult it is useful for the real time visualisers such as the IMU.
  • Read and display buffer usage is displayed to allow tuning and warn of either the PC or the Arduino generating too much data for the other.
 

Step 2: Message Sender

 Message Sender 
 
  • This allows data to be sent outbound on the COM port and controls whether the output is included in the trace window.
  • Control whether the output is not sent out but simply looped back. This is used for convenient experiments with data streams to see how they work with the various forms and visualisers.
  • A looping tool allows multiple parameter substitution and repeats.
  • A joypad simulation with user adjustable data.
  • A keypad simulation with user adjustable data.
  • A slider tool with user adjustable data.

Step 3: Trace Copy

Trace copy 
 
  • This allows you to review the trace output while the main trace window is running.
  • This contains the text of the trace window when requested for by either the user or the Arduino.

Step 4: LCD Emulator

LCD emulator 
 
  • 80 columns by 25 rows.
  • Write text anywhere on the ‘screen’ in any of 7 colours for foreground and background.
  • Scroll command to you can treat it like a TTY display.
  • Make up your own user interface.

Step 5: Freeform Drawing Surface

Freeform drawing surface 
 
  • 500 pixels by 500 pixels drawing surface.
  • Commands for line, rectangle ellipse, arc and pie, filled and unfilled, cross and text, in various sizes and orientations and in 5 colours.
  • For example plot out your robot path.

Step 6: Alert Reporter

Alert reporter  
 
  • Somewhere to report special events to the user.
  • Option to send run commands to start programs.
  • Beeps to alert user

Step 7: PS3 Controller Visualiser

PS3 controller visualiser 
 
  • Displays PS3 or similar controller button and joystick values.
  • Green shows values unchanged since last reading.
  • Orange shows values that have changed since last reading.
  • Red shows values that are at maximum.
  • Joystick position cross hairs.
  • Useful for watching what the controller is sending to your robot for example.
  • See how sensitive the different buttons are.
  • Note if the joysticks are not self centering or minimum/maximum values not reached.
  • Pause ‘able. 

Step 8: XY Scatter Plotter

XY scatter plotter 
 
  • See the relationship between two values for up to five different sets.
  • Easy user control of axis settings.
  • Pause ‘able. 

Step 9: Sweep Plotter

Sweep plotter 
 
  • Trace like oscilloscope.
  • Five traces with a resolution between 10 and 1024 points.
  • Easy user control of axis settings.
  • For example watch accelerometer and gyro readings.
  • Pause ‘able.
  • Auto scaling option.
  • Toggle between data and keys.
  • Pause ‘able. 

Step 10: Histogram Plotter

Histogram plotter
 
  • 21 bar histogram.
  • Shows percentage of observations and count of observations.
  • Easy user control of axis settings.
  • Over and under range outlier recording.
  • Simple statistics - mean, min and max of within range observations.
  • Pause ‘able. 

Step 11: IMU Visualiser

IMU visualiser 
 
  • Roll and pitch visualisation.
  • Invert option to suit installed orientation of breakout board.
  • Accelerometer and gyroscope readings (including gyro drift summation).
  • Pause ‘able. 

Step 12: Hints for Those Wanting to Do It Themselves

Hints for those wanting to do it themselves
 
  • It was interesting to discover that to my UNO and Mega did not work reliably at 300 baud and the buffering of data between them and the PC is also different. These differences are not noticeable in ‘normal’ conditions but show up at the limit of performance such as when transmitting a lot of data very quickly, in either direction and at the lower or higher baud rates. Make sure you test at the full range of performance and with different hardware as they do not behave exactly the same.
  • .NET exception handling isn’t very fast so do all your own data checks otherwise the program will slow and the Arduino will send out data faster than it is being processed on the PC.
  • Multi threading is a must as you need to get the reading of the serial input stream done as fast as possible and into buffers the various forms can the handle for displaying to the user.
  • Data can come so fast that it is impossible for a user to read every change unless it is a plot type of display. Therefore don’t bother to update display data for every single character as it changes. This will clog the PC down even though the display processing is done in a separate thread - remember there is only a finite amount of processing available and multi threading doesn’t make more of it, it just reassigns it differently.
  • Factors outside of the Arduino and the serial monitor can affect its performance. I leave the program on soak testing overnight receiving data pumped out at maximum speed from the Arduino. That means thousands and thousands of lines of data and I’ll notice that at say 2am in the morning one line will be in error - typically the length it is and the length it should be don’t agree. I can only assume a virus check has kicked in and messed something up. While this may be an exceptionally small percentage of the data it might result in a serious consequence in your system.
  • Check the data received is expected and error handle if it is not. For all the special commands used in the serial monitor I send the length of the data as well as the data from the Arduino and I also check it on the serial monitor. If they don’t agree I don’t send the data to the appropriate visualise form but send what has been captured to the Alert visualise for the user to aware that something has gone wrong. I have considered using a CRC checksum but the added processing time doesn’t, for me, warrant it over simple line length checks.
  • As much as you would like to avoid getting the user involved in tuning the system at the extremes of what your PC can cope with it can buffer up a lot of data which means the visualisation displays lag behind the Arduino’s actual behaviour. In my first versions of this tool I surfaced a lot of tuning parameters before settling on two that were really useful/unavoidable. Reading all bytes as soon as theyare available versus the much slower read a line at a time (useful when you are sending data back to the Arduino and scheduling it into the correct sequence is important) and slowing the displays down to allow them to update in ‘chunks’ makes it easier to read fast changing listings.
  • Don’t expect it to be right first time. I had a couple of technical proof of concepts (during which I found that some code available on the Internet was faulty with a slow but steady memory leak). Once it works fast and reliably then you can refine the user interface to give the features you need and also make them convenient to use. This is version 3.
  • Processing binary data may be more compact/faster but cannot be viewed in the Arduino IDE which is a convenient fall back option to testing.
You will have to take a &lsquo;leap of faith&rsquo; at some stage and buy some kit even to test out the code. It will be impossible to develop something that will work without testing and that will almost certainly require you to get the motors, motor controller and switches even if you don&rsquo;t buy or make the robot chassis/body in the first instance. I think the minimum you could simulate would be to attach the switches and the LEDs and watch their behaviour and send the motor control output as text data to the serial port. This would get a long way to getting the logic correct. <br> <br>If this code has been successful in someone else&rsquo;s robot then it can be in another one - yours - but you will have to confirm that it applies to your configuration. I am not in a position to test/develop the code you have posted. <br> <br>You will have to learn how to program and debug code - it sounds like this is a skill you don&rsquo;t yet have. Syntactically correct code, as you say does not mean the logic is correct. Only the most trivial programs will work straight away. You will have to &lsquo;dump&rsquo; your variables values out for you to review and understand what the code is doing and compare it with what your robot is doing to be able to make progress. <br> <br>I&rsquo;d be interested to know what your motivation is for this project. <br>
hey,friend it's look like u have a great knowlage on arduino i need ur help,i m new to arduino..i want to run arduino programme which i'hv (made for leonardo board only) and check whether there is any error in programme or not..and than i want to upload this programme in programme board and acorrding to programme it'll run 2 gear motor,so how can i check it and load it..can u please tell me step wise instruction or put instructable type vedio..i'll be thankfull,thank you
Creasty, <br>You ask for something but have not given enough background to allow any better answer than look on the internet as there is lots of information about: <br>- Debugging programs - in general and specifically for the Arduino <br>- How to upload programs to Arduino <br>- Ways to control motors - everything from 5v hobby motors to large motors used in mobility scooters <br>- Lots of sample sketches for all the different parts of this problem <br> <br>Here are some questions for you which might help getting some answers: <br> <br>- What is your level of experience and with what tools/environment? <br>- What is your time scale to carry out the project? <br>- What is your budget for the project? <br>- What resources can you call upon - others in the team, if any? <br>- How &lsquo;well finished&rsquo; does the project have to be? Proof of concept or production, for example. <br>And most important what is it you are actually doing? <br>
thank u for replay,i'm going to tell u overview of my problem. i'm working on 'arduino leonardo'....it's for 'obstacle avoider robot' jumper is used for obstacle avoiding(basicaly jumper is a copper wire that is placed on edge of robot(both front and back side)and connected with arduino.whenever jumper toches any obstacles robot will change it's direction of moving.this is done through 'arduino' +motor driver + 2 dc gear motor program i'hv put attech here(in the next comment) <br> <br>i need your help in this case..i wanted to know that is this programme is simply correct? <br>i'hv checked it's syntcs in arduino software &gt; sketch&gt; compile/verify &gt;result compile done it's showing no error...it means syntcs are right..but what about all logic used here? <br> <br>i got this one from internet,so without surety i don't want to purchase expensive componant for this robot. <br> <br>so can u help me in this case that the program logic is correct,nd if u have this board can u tell me by running this programme,(evenif suppose motor will start moving i'll be happy!) <br> <br>this are the main confusion for biginners that arduino compiler is showing no syntcs error and if there's any mistake or logic problem in program,how one can detect it? or correct it? <br> <br>i'll be thankfull. <br> <br>thank u.
/* <br>Program for controlling a robot with two motors. <br>The robot turns when motors changes their speed and direction. <br>Front bumpers on left and right sides detect obstacles. <br>LED is turned on when any of bumpers are pressed. <br>When porgram starts it waits while one of bumpers is pressed and than runs motors forward. <br>*/ <br> <br>const int pinLED = 13; <br>//right side <br>const int pinRightMotorDirection = 2; <br>const int pinRightMotorSpeed = 3; <br>const int pinRightBumper = 7; <br>//left side <br>const int pinLeftMotorDirection = 4; <br>const int pinLeftMotorSpeed = 5; <br>const int pinLeftBumper = 8; <br> <br>//fields <br>const int turnTimeout = 100; <br>boolean led; <br>//set in counter how long a motor is running back: N/10 (in milliseconds) <br>int countDownWhileMovingToRight; <br>int countDownWhileMovingToLeft; <br> <br>//Initialization <br>void setup() { <br> <br> initPins(); <br> <br> waitWhileAnyBumperIsPressed(); <br> <br> runRightMotorForward(); <br> runLeftMotorForward(); <br>} <br> <br>//Main loop <br>void loop() { <br> <br> verifyAndSetRightSide(); <br> verifyAndSetLeftSide(); <br> <br> processRightSide(); <br> processLeftSide(); <br> <br> turnOnLEDIfAnySideRunsBackward(); <br> <br> delay(10);//repeat every 10 milliseconds <br>} <br> <br>//--------------------------------------------------- <br>void initPins(){ <br> pinMode(pinLED, OUTPUT); <br> pinMode(pinRightMotorDirection, OUTPUT); <br> pinMode(pinRightMotorSpeed, OUTPUT); <br> pinMode(pinRightBumper, INPUT); <br> pinMode(pinLeftMotorDirection, OUTPUT); <br> pinMode(pinLeftMotorSpeed, OUTPUT); <br> pinMode(pinLeftBumper, INPUT); <br>} <br> <br>void waitWhileAnyBumperIsPressed(){ <br> while(checkBumperIsNotPressed(pinRightBumper) <br> &amp;&amp; checkBumperIsNotPressed(pinLeftBumper)){ <br> delay(20);//check every 20 milliseconds <br> } <br>} <br> <br>void processRightSide(){ <br> if(countDownWhileMovingToRight &lt;= 0)//checks if counter was NOT ran when bumper had been pressed <br> return; <br> //otherwise - counter is counting downd (as a delay) while the right motor is moving backward <br> countDownWhileMovingToRight--;//decrease the counter if it WAS ran when bumper had been pressed <br> if(countDownWhileMovingToRight &lt;= 0)//if the running counter got down to zero <br> runRightMotorForward();//run the right motor forward <br>} <br> <br>void processLeftSide(){ <br> if(countDownWhileMovingToLeft &lt;= 0) <br> return; <br> countDownWhileMovingToLeft--; <br> if(countDownWhileMovingToLeft &lt;= 0) <br> runLeftMotorForward(); <br>} <br> <br>void verifyAndSetRightSide(){ <br> if(checkBumperIsNotPressed(pinRightBumper))//checks if right bumper has NOT been pressed <br> return; <br> if(checkCounterIsNotSet(countDownWhileMovingToRight))//if the counter is not yet counting down <br> runRightMotorBackward();//run the right motor backward <br> countDownWhileMovingToRight = turnTimeout;//set the counter to maximum value to start it counting down <br>} <br> <br>void verifyAndSetLeftSide(){ <br> if(checkBumperIsNotPressed(pinLeftBumper)) <br> return; <br> if(checkCounterIsNotSet(countDownWhileMovingToLeft)) <br> runLeftMotorBackward(); <br> countDownWhileMovingToLeft = turnTimeout; <br>} <br> <br>bool checkCounterIsNotSet(int counter){ <br> return counter &lt;= 0; <br>} <br> <br>bool checkBumperIsNotPressed(int pinBumper){ <br> return digitalRead(pinBumper); <br>} <br> <br>void runRightMotorForward(){ <br> runMotorForward(pinRightMotorDirection, pinRightMotorSpeed); <br>} <br> <br>void runLeftMotorForward(){ <br> runMotorForward(pinLeftMotorDirection, pinLeftMotorSpeed); <br>} <br> <br>void runRightMotorBackward(){ <br> runMotorBackward(pinRightMotorDirection, pinRightMotorSpeed); <br>} <br> <br>void runLeftMotorBackward(){ <br> runMotorBackward(pinLeftMotorDirection, pinLeftMotorSpeed); <br>} <br> <br>void runMotorForward(int pinMotorDirection, int pinMotorSpeed){ <br> digitalWrite(pinMotorDirection, true); //set direction forward <br> analogWrite(pinMotorSpeed, 0); //set max speed forward (127 is for stop) <br>} <br> <br>void runMotorBackward(int pinMotorDirection, int pinMotorSpeed){ <br> digitalWrite(pinMotorDirection, false); //set direction backward <br> analogWrite(pinMotorSpeed, 255); //set max speed backward (127 is for stop) <br>} <br> <br>void turnOnLEDIfAnySideRunsBackward(){ <br> digitalWrite(pinLED, oneOrBothMotorsAreRunninsBack()); <br>} <br> <br>bool oneOrBothMotorsAreRunninsBack(){ <br> return (countDownWhileMovingToRight &gt; 0 || countDownWhileMovingToLeft &gt; 0); <br>}
/* <br>Program for controlling a robot with two motors. <br>The robot turns when motors changes their speed and direction. <br>Front bumpers on left and right sides detect obstacles. <br>LED is turned on when any of bumpers are pressed. <br>When porgram starts it waits while one of bumpers is pressed and than runs motors forward. <br>*/ <br> <br>const int pinLED = 13; <br>//right side <br>const int pinRightMotorDirection = 2; <br>const int pinRightMotorSpeed = 3; <br>const int pinRightBumper = 7; <br>//left side <br>const int pinLeftMotorDirection = 4; <br>const int pinLeftMotorSpeed = 5; <br>const int pinLeftBumper = 8; <br> <br>//fields <br>const int turnTimeout = 100; <br>boolean led; <br>//set in counter how long a motor is running back: N/10 (in milliseconds) <br>int countDownWhileMovingToRight; <br>int countDownWhileMovingToLeft; <br> <br>//Initialization <br>void setup() { <br> <br> initPins(); <br> <br> waitWhileAnyBumperIsPressed(); <br> <br> runRightMotorForward(); <br> runLeftMotorForward(); <br>} <br> <br>//Main loop <br>void loop() { <br> <br> verifyAndSetRightSide(); <br> verifyAndSetLeftSide(); <br> <br> processRightSide(); <br> processLeftSide(); <br> <br> turnOnLEDIfAnySideRunsBackward(); <br> <br> delay(10);//repeat every 10 milliseconds <br>} <br> <br>//--------------------------------------------------- <br>void initPins(){ <br> pinMode(pinLED, OUTPUT); <br> pinMode(pinRightMotorDirection, OUTPUT); <br> pinMode(pinRightMotorSpeed, OUTPUT); <br> pinMode(pinRightBumper, INPUT); <br> pinMode(pinLeftMotorDirection, OUTPUT); <br> pinMode(pinLeftMotorSpeed, OUTPUT); <br> pinMode(pinLeftBumper, INPUT); <br>} <br> <br>void waitWhileAnyBumperIsPressed(){ <br> while(checkBumperIsNotPressed(pinRightBumper) <br> &amp;&amp; checkBumperIsNotPressed(pinLeftBumper)){ <br> delay(20);//check every 20 milliseconds <br> } <br>} <br> <br>void processRightSide(){ <br> if(countDownWhileMovingToRight &lt;= 0)//checks if counter was NOT ran when bumper had been pressed <br> return; <br> //otherwise - counter is counting downd (as a delay) while the right motor is moving backward <br> countDownWhileMovingToRight--;//decrease the counter if it WAS ran when bumper had been pressed <br> if(countDownWhileMovingToRight &lt;= 0)//if the running counter got down to zero <br> runRightMotorForward();//run the right motor forward <br>} <br> <br>void processLeftSide(){ <br> if(countDownWhileMovingToLeft &lt;= 0) <br> return; <br> countDownWhileMovingToLeft--; <br> if(countDownWhileMovingToLeft &lt;= 0) <br> runLeftMotorForward(); <br>} <br> <br>void verifyAndSetRightSide(){ <br> if(checkBumperIsNotPressed(pinRightBumper))//checks if right bumper has NOT been pressed <br> return; <br> if(checkCounterIsNotSet(countDownWhileMovingToRight))//if the counter is not yet counting down <br> runRightMotorBackward();//run the right motor backward <br> countDownWhileMovingToRight = turnTimeout;//set the counter to maximum value to start it counting down <br>} <br> <br>void verifyAndSetLeftSide(){ <br> if(checkBumperIsNotPressed(pinLeftBumper)) <br> return; <br> if(checkCounterIsNotSet(countDownWhileMovingToLeft)) <br> runLeftMotorBackward(); <br> countDownWhileMovingToLeft = turnTimeout; <br>} <br> <br>bool checkCounterIsNotSet(int counter){ <br> return counter &lt;= 0; <br>} <br> <br>bool checkBumperIsNotPressed(int pinBumper){ <br> return digitalRead(pinBumper); <br>} <br> <br>void runRightMotorForward(){ <br> runMotorForward(pinRightMotorDirection, pinRightMotorSpeed); <br>} <br> <br>void runLeftMotorForward(){ <br> runMotorForward(pinLeftMotorDirection, pinLeftMotorSpeed); <br>} <br> <br>void runRightMotorBackward(){ <br> runMotorBackward(pinRightMotorDirection, pinRightMotorSpeed); <br>} <br> <br>void runLeftMotorBackward(){ <br> runMotorBackward(pinLeftMotorDirection, pinLeftMotorSpeed); <br>} <br> <br>void runMotorForward(int pinMotorDirection, int pinMotorSpeed){ <br> digitalWrite(pinMotorDirection, true); //set direction forward <br> analogWrite(pinMotorSpeed, 0); //set max speed forward (127 is for stop) <br>} <br> <br>void runMotorBackward(int pinMotorDirection, int pinMotorSpeed){ <br> digitalWrite(pinMotorDirection, false); //set direction backward <br> analogWrite(pinMotorSpeed, 255); //set max speed backward (127 is for stop) <br>} <br> <br>void turnOnLEDIfAnySideRunsBackward(){ <br> digitalWrite(pinLED, oneOrBothMotorsAreRunninsBack()); <br>} <br> <br>bool oneOrBothMotorsAreRunninsBack(){ <br> return (countDownWhileMovingToRight &gt; 0 || countDownWhileMovingToLeft &gt; 0); <br>}
thank u for replay,i'm going to tell u overview of my problem. i'm working on 'arduino leonardo'....it's for 'obstacle avoider robot' jumper is used for obstacle avoiding(basicaly jumper is a copper wire that is placed on edge of robot(both front and back side)and connected with arduino.whenever jumper toches any obstacles robot will change it's direction of moving.this is done through 'arduino' +motor driver + 2 dc gear motor program i'hv put attech here(in the next comment) <br> <br>i need your help in this case..i wanted to know that is this programme is simply correct? <br>i'hv checked it's syntcs in arduino software &gt; sketch&gt; compile/verify &gt;result compile done it's showing no error...it means syntcs are right..but what about all logic used here? <br> <br>i got this one from internet,so without surety i don't want to purchase expensive componant for this robot. <br> <br>so can u help me in this case that the program logic is correct,nd if u have this board can u tell me by running this programme,(evenif suppose motor will start moving i'll be happy!) <br> <br>this are the main confusion for biginners that arduino compiler is showing no syntcs error and if there's any mistake or logic problem in program,how one can detect it? or correct it? <br> <br>i'll be thankfull. <br> <br>thank u. <br>
If it had been made in java, we could have integrated it into an eclipse plugin which would have been awesome for the arduino platform. So why .net?
.NET is something I'm familiar with and has everything I need in one place and as a complete solution won't need anything more than Microsoft/Windows software to run - in which case its simple for everybody to get it up and running. <br>

About This Instructable

13,040views

60favorites

License:

More by acboother:Robotic Legs Arduino Development Tool Homeduino 
Add instructable to: