Puppy Linux Discussion Forum Forum Index Puppy Linux Discussion Forum
Puppy HOME page : puppylinux.com
"THE" alternative forum : puppylinux.info
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

The time now is Tue 25 Sep 2018, 02:47
All times are UTC - 4
 Forum index » Off-Topic Area » Programming
GUI dialog tool and serial IO (Solved)
Post new topic   Reply to topic View previous topic :: View next topic
Page 1 of 1 [7 Posts]  
Author Message
Uten


Joined: 29 Jan 2008
Posts: 124

PostPosted: Wed 31 Jan 2018, 02:14    Post subject:  GUI dialog tool and serial IO (Solved)
Subject description: Need advice and examples
 

Hello,

For my arduino projects I have started to wonder if it possible to use some kind of dialog program, like GtkDialog, and serial communication to make a frontend on a PC.

I want as few dependencies as possible.

From the top of my head I think I can make a dialog and send commands down the serial ( /dev/ttyUSB0 ) line. But I don't know how to read values back from the serial line asynchronously.

This code will do in a terminal
Code:
#!/bin/bash
# interactive serial communication over usb port
# I tried it against arduino uno program
#
# SOURCE: https://unix.stackexchange.com/questions/22545/how-to-connect-to-a-serial-port-as-simple-as-using-ssh/311680#311680
#
if [[ $# -lt 1 ]]; then
    echo "Usage:"
    echo "  femtocom <serial-port> [ <speed> [ <stty-options> ... ] ]"
    echo "  Example: $0 /dev/ttyS0 9600"
    echo "  Press Ctrl+Q to quit"
fi

# Exit when any command fails
set -e

# Save settings of current terminal to restore later
original_settings="$(stty -g)"

# Kill background process and restore terminal when this shell exits
trap 'set +e; kill "$bgPid"; stty "$original_settings"' EXIT

# Remove serial port from parameter list, so only stty settings remain
port="$1"; shift

# Set up serial port, append all remaining parameters from command line
stty -F "$port" raw -echo "$@"

# Set current terminal to pass through everything except Ctrl+Q
# * "quit undef susp undef" will disable Ctrl+\ and Ctrl+Z handling
# * "isig intr ^Q" will make Ctrl+Q send SIGINT to this script
# NOTE: This line did not work for me.
#stty raw -echo isig intr ^Q quit undef susp undef

# Let cat read the serial port to the screen in the background
# Capture PID of background process so it is possible to terminate it
cat "$port" & bgPid=$!

# Redirect all keyboard input to serial port
#cat >"$port"
while read cmd
do
   echo "$cmd"
done > "$port"


So I would like to capture stuff from the line
Code:
cat "$port" & bgPid=$!
Parse it and update my gui with the values.
This part
Code:
while read cmd
do
   echo "$cmd"
done > "$port"
would be replaced with GUI elements like buttons etc.

Anyone know of examples or solutions I might use?

Last edited by Uten on Mon 05 Feb 2018, 07:07; edited 1 time in total
Back to top
View user's profile Send private message 
technosaurus


Joined: 18 May 2008
Posts: 4834
Location: Kingwood, TX

PostPosted: Wed 31 Jan 2018, 21:26    Post subject:  

There are plenty of examples in the gtkdialog tips thread as well as the gtkdialog source, but the best way is to look at the script of a program that does something similar to what you want.
_________________
Check out my github repositories. I may eventually get around to updating my blogspot.
Back to top
View user's profile Send private message Visit poster's website 
jafadmin

Joined: 19 Mar 2009
Posts: 845

PostPosted: Fri 02 Feb 2018, 22:55    Post subject:  

It is worth noting that picocom or minicom are included with most puppies.
https://linux.die.net/man/8/picocom

It can also send and receive files over the serial port
Back to top
View user's profile Send private message 
Uten


Joined: 29 Jan 2008
Posts: 124

PostPosted: Mon 05 Feb 2018, 07:01    Post subject:  

@jafadmin: semms like minicom and picocom is left out in fatdog. A terminal cli solution is to use
Code:
platformio device monitor
witch launch a miniterm.py session with some custom settings.

Anyway this is what I have come up with. It works for personal quick fix use. But I guess a pyGTK and miniterm.py is a reasonable trade-off if you need something more serious.

The most important tricks are probably the stty configuration and the timer trick in gtkdialog to get "asynchronous" updates. You may use multiple timers.

My bash script:
Code:
#! /bin/bash

#
# Demo program making a GUI interface against a arduino uno micro
# controller.
#
# RESOURCE: https://playground.arduino.cc/Interfacing/LinuxTTY
#
# NOTICE: This "works" but is not a stable solution. The arduino board
#         resets when the dialog is connected. This is done as part of
#         the stty call (or first read in the backround loop).
#
#         Sometimes the ttyUSB0 connection will "hang". When it do I
#         I reset it with this commend:
#
#                modprobe -r ch341 && sleep 3 && modprobe ch341
#
#         You will have to replace the module ch341 with the one in use
#         on your system.
#
#

#
# The serial device to use
export port="/dev/ttyUSB0"
#
# Save original config from device
stty_orig="$(stty -g)"
#
# a file in /dev/shm/ is in memmory
export file="/dev/shm/foo"
#
# The stty configuration has to be right to get reliable communication.
# Most samples on the net use only stty /dev/tty[] 9600 which is to
# little
stty -F "$port" cs8 9600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr \
      -isig -icanon -iexten -echo -echoe -echok -echoctl \
      -echoke noflsh -ixon -crtscts


echo "initiated" > "$file"
# Background loop / process to read from arduino board


#
# Make a sub shell to read from the serial port
#
# The simple solution, but it also can generate huge files. maybe use it
# for logging?
#cat "$port" > $file &
#
# A read loop that works for this sample
export   prev=""
while read -r line; do
   if [[ "$line" != "" ]] && [[ "$prev" != "$line" ]]; then
      # TODO: Part of this line disappears? We should get a line
      # cmdSend: [<command>]
      # (40) line:=<command> <--> prev:=<previous command>
      echo "($LINENO) line:=$line <--> prev:=$prev"
      echo "$line" >> "$file"
      prev="$line"
   else
      sleep .1
   fi   
done < "$port"  &

#
# Save pid of sub shell so we can clean up later
bgPid=$!
if [ "$bgPid" == "0" ]; then
   echo "ERROR: Reading serial device failed"
   exit 1
fi

#
# Trap exit and cleanup background process
trap 'set +e; stty "$stty_orig";rm -f "$file"; kill "$bgPid"' EXIT

#
# helper function. Must be exported to be called by gtkdialog
function cmdSend() {
   echo "$1" > "$port"
   echo "cmdSend: [$1]"
}; export -f cmdSend

cmdSend "version"

function getLastLine() {
   #sed -n '$p' "$file"   
   if [ -f "$file" ]; then
      #cat "$file"
      tail --lines=3 "$file"
   fi
}; export -f getLastLine


#
# This is the code used by gtkdialog. notice the timer (last part)
# to update the information label. This is how we get values
# from the arduino device.
export MAIN_DIALOG='
<vbox>
    <text>
      <label>--- Crane demo ---</label>
    </text>
   <button>
        <label>demo</label>
        <action>cmdSend "demo"</action>
   </button>
   <button>
      <label>up</label>
      <action>cmdSend "up"</action>
   </button>
<hbox>
   <button>
      <label>left</label>
      <action> cmdSend "left"</action>
   </button>
   <button>
      <label>stop</label>
      <action> cmdSend "stop"</action>
   </button>
   <button>
      <label>right</label>
      <action> cmdSend "right"</action>
   </button>
</hbox>
   <button>
      <label>down</label>
      <action> cmdSend "down"</action>
   </button>
  <text>
  <variable>MSG</variable>
  <input> getLastLine </input>
 </text>
 <timer milliseconds="true" interval="250" visible="false">
  <action type="refresh">MSG</action>
 </timer>      
</vbox>
'

#
# gtkdialog
gtkdialog --program=MAIN_DIALOG

#cat "$file"
exit 0

My scetch (I use platformio to compile/upload to arduino board)
Code:
/*
Into Robotics
*/
#include <SerialCommand.h>

bool bRunning=false;
int arduinoLed=13;
int x1 = 2; /* x axis motor relay 1 */
int x2 = 3; /* x axis motor relay 2 */
int y1 = 4; /* y axis motor relay 1 */
int y2 = 5; /* y axis motor relay 2 */

SerialCommand sCmd;

unsigned long uTime=0;

void setup()
{
   // Setup output ports used by relay board
   all_output( x1, x2, y1, y2);
   /* The 4 Relay Module SBX board has default high=off */
   off( x1, x2);
   off( y1, y2);

   // Turn off default internal led
   pinMode(arduinoLed, OUTPUT);
   digitalWrite(arduinoLed,LOW);

   // Setup serial communication, could be faster
   Serial.begin(9600);

   // Setup serial command interface
   sCmd.addCommand("right", SCMD_right );
   sCmd.addCommand("left", SCMD_left );
   sCmd.addCommand("up", SCMD_up );
   sCmd.addCommand("down", SCMD_down );
   sCmd.addCommand("stop", SCMD_stop);
   sCmd.addCommand("demo", demo);
   sCmd.addCommand("help", help);
   sCmd.addCommand("version", version);
   sCmd.setDefaultHandler(SCMD_error);
   Serial.flush();
}
void demo() {
   Serial.println("Demo start");
   left(x1, x2);
   delay(2000);
   off(x1, x2);
   delay(2000);
   right(x1, x2);
   delay(2000);
   off(x1, x2);
   delay(2000);
   Serial.println("Demo end");
}
void version() {
   Serial.println("Version: 0.1");
}
void help() {
   Serial.println("Available commands");
   Serial.println("right - Turn crane right");
   Serial.println("left  - Turn crane left");
   Serial.println("up    - Hoist hook");
   Serial.println("down  - Lower hook");
   Serial.println("stop  - Stop all actions");
   Serial.println("demo  - Run a demo");
   Serial.println("help  - Print this help");
   Serial.println("version - Print version information");
}
void all_output(int r1, int r2, int r3, int r4) {
   pinMode(r1, OUTPUT);
   pinMode(r2, OUTPUT);
   pinMode(r3, OUTPUT);
   pinMode(r4, OUTPUT);
}
void off(int r1, int r2) {
   digitalWrite(r1, HIGH);
   digitalWrite(r2, HIGH);
   bRunning=true;
}
void left(int r1, int r2) {
   digitalWrite(r1, LOW);
   digitalWrite(r2, HIGH);
   bRunning=true;
}
void right(int r1, int r2){
   digitalWrite(r1, HIGH);
   digitalWrite(r2, LOW);
   bRunning=true;
}

void SCMD_left() {
   left(x1, x2);
   uTime=millis();
   Serial.println("left");
}
void SCMD_right() {
   right(x1,x2);
   uTime=millis();
   Serial.println("right");
}
void SCMD_up() {
   right(y1,y2);
   uTime=millis();
   Serial.println("up");
}
void SCMD_down() {
   left(y1, y2);
   uTime=millis();
   Serial.println("down");
}
void SCMD_stop() {
   off(x1, x2);
   off(y1, y2);
   bRunning=false;
   uTime=millis()-uTime;
   Serial.println("stop");
   
}
void SCMD_error(const char *command) {
   SCMD_stop();
   Serial.print("Unrecognized command,[");
   Serial.print(command);
   Serial.println("]");

}
void loop() {
   if (Serial.available() >0){
      sCmd.readSerial();
      Serial.flush();
   } else {
      delay(250);
   }
}


Happy coding
uten
Back to top
View user's profile Send private message 
jamesbond

Joined: 26 Feb 2007
Posts: 3158
Location: The Blue Marble

PostPosted: Mon 05 Feb 2018, 10:30    Post subject:  

Quote:
@jafadmin: semms like minicom and picocom is left out in fatdog. A terminal cli solution is to use

Fatdog comes with microcom (part of busybox). But microcom is useful for interactive sessions.
For programmatic read/write, "echo" and "cat" and "read" is better. You need to stop the board from resetting, though, do "stty -F /dev/ttyUSB0 -hupcl" - see https://arduino.stackexchange.com/a/16779. Of put 10uF cap between reset line and the ground.

_________________
Fatdog64, Slacko and Puppeee user. Puppy user since 2.13.
Contributed Fatdog64 packages thread.
Back to top
View user's profile Send private message 
mister_electronico


Joined: 20 Jan 2008
Posts: 960
Location: Asturias_ España

PostPosted: Sun 04 Mar 2018, 10:06    Post subject:  

very interesting , can that maybe you are interested in this.

http://www.murga-linux.com/puppy/viewtopic.php?p=877473#877473

video

https://www.youtube.com/watch?v=qrVFsOH82i4

see you
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger 
Uten


Joined: 29 Jan 2008
Posts: 124

PostPosted: Thu 08 Mar 2018, 00:47    Post subject:    

Thanks for the input guys. Sorry for the late replies. I'm not very active online these days.

Your right @Jamesbond microcom is part of fatdog. I must have typed it wrong when I tested.

After I got the stty init right I have not had much trouble with communication. I have just used it on board (Chines knock of uno board from aliexpress). But I will keep the reset call in my notes for later use.

looks like a nice project you have there @mister_electronico.

Happy coding
Uten
Back to top
View user's profile Send private message 
Display posts from previous:   Sort by:   
Page 1 of 1 [7 Posts]  
Post new topic   Reply to topic View previous topic :: View next topic
 Forum index » Off-Topic Area » Programming
Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group
[ Time: 0.0737s ][ Queries: 11 (0.0093s) ][ GZIP on ]