Interface and Application Programming

Interface programming is a lesson that connects the end user via a visible computer input and/or output interface to the device output and/or input, respectively. I have reviewed several interfaces.

Interfaces reviewed

Scratch

I have used Scratch for its usability. But I have not been able to connect it to my board. I tryed connecting Scratch with an Arduino. But my browser is not able to use the Javascript on that page for making the connection to the USB port where TeleKIT is plugged.

My Scratch application helps a cat chase a sailboat by following the mouse pointer. When it reaches the sailboat, it stops and lights a LED on the board.

scratch application image

Arduino IDE with BASh

I have modified several scripts from the Arduino example scripts to:

Terminal to Arduino and back

echo "Send this message to Arduino UNO" > /dev/ttyACM0

It is visible via the Arduino serial console. I have not been able to receive the output of the program as is supposed to with

tail -f /dev/ttyACM0

Phototransistor to terminal

By connecting a phototransistor to pin 2, we can send to the computer serial port the binary data it detects. It can be read through the tail command. Here is the code copied via the Arduino IDE html function:

      /*
        DigitalReadSerial
       Reads the light provision, prints the result to the serial monitor 
       
       This example code is licensed by Quiliro 2018 GNU GPLv3.
       */

      // digital pin 2 has a phototransistor attached to it. Give it a name:
      int photoTrans = 2;

      // the setup routine runs once when you press reset:
      void setup() {
        // initialize serial communication at 9600 bits per second:
        Serial.begin(9600);
        // make the pushbutton's pin an input:
        pinMode(photoTrans, INPUT);
      }

      // the loop routine runs over and over again forever:
      void loop() {
        // read the input pin:
        int lightState = digitalRead(photoTrans);
        // print out the state of the button:
        Serial.println(lightState);
        delay(1);        // delay in between reads for stability
      }

    

Blink LED

      /*
       BlinkFull
       Turns on an LED on, then as fast as it can.
       
       This example code is licensed by Quiliro 2018 GNU GPLv3..
       */

      // Pin 13 has a LED connected on most Arduino boards.
      // I give it a name:
      int led = 13;              // LED's pin

      // the setup routine runs once when you press reset:
      void setup() {                
        // initialize the LED's pin as an output.
        pinMode(led, OUTPUT);
      }

      // the loop routine runs over and over again forever:
      void loop() {

            // turn the pin on:
            digitalWrite(led, HIGH);
            delay(30);
            // turn the pin off:
            digitalWrite(led, LOW);
            delay(30);
      }

    

Reset LED

      /*
        ResetLED
       Turns on the onboard LED off.
       
       This example code is licensed by Quiliro 2018 GNU GPLv3..
       */

      // Pin 13 has a LED connected on most Arduino boards.
      // I give it a name:
      int led = 13;              // LED's pin

      // the setup routine runs once when you press reset:
      void setup() {                
        // initialize the LED's pin as an output.
        pinMode(led, OUTPUT);
      }

      void loop() {

            // turn the pin off:
            digitalWrite(led, LOW);


      }

    

Sample communication

At a tutorial for BASh connection with Arduino, there is an Arduino script which will not go through Arduino IDE verification because the line:

// [ Enter ] else if ( int(inChar) == 13 ) {

should be:

// [ Enter ]

else if ( int(inChar) == 13 ) {

So the script runs correctly with the code as follows:

      String inputString = "";

      String lastcmd = "";

      boolean stringComplete = false;

      int sensor = A0;

      int ledstate = LOW;

      //use some wiring from this pin to reset pin to disable auto-reset

      int resetPin = 8;

      //Check if inputString match the given cmd string

      bool cmd(String cmd){

        if (inputString.startsWith(cmd)){ 
          return true;
        }
        else { 
          return false; 
        }

      }

      //Simply blink the led for some time

      void blink(int led, int mil){

        digitalWrite(led,HIGH);  
        delay(mil);
        digitalWrite(led,LOW);  
        delay(mil);

      }

      //This function will restart your board

      void(* reboot) (void) = 0;

      void setup() {

        //Set the serial port speed

        Serial.begin(115200);
        inputString.reserve(255);
        pinMode(13,OUTPUT);

        //with some wiring from the resetPin (pin 8) to the reset pin, this will disable auto-restart

        digitalWrite(resetPin,HIGH);

        //blink 3 times to show that system is starting

        blink(13,200);
        blink(13,200);
        blink(13,200);

        //print a cool penguin and initial prompt

        Serial.println("  .^.");
        Serial.println("  /\V\\");
        Serial.println(" / - \\");
        Serial.println("/(   )\\");
        Serial.println(" ^`~'^");
        Serial.print("Arduino:");

      }

      //Perform actions based on the input

      void check_input(String input){

        //if the input is an exclamation, repeat last command

        if(cmd("!")){ 
          inputString = lastcmd;
        }

        //Turn led on

        if (cmd("led_on")){

          ledstate = HIGH;
          Serial.println("LED was turned on");

          //Turn led off

        } 
        else if (cmd("led_off")) {

          ledstate = LOW;
          Serial.println("LED was turned off");

          //Read sensor pin

        } 
        else if (cmd("read_sensor")) {

          Serial.println("Sensor value was:"+String(analogRead(sensor)));

          //Call blink function

        } 
        else if (cmd("blink")) {

          blink(13,200);

          blink(13,200);

          blink(13,200);

          //Call reboot

        } 
        else if (cmd("reboot")) {

          Serial.println("Rebooting...");
          delay(200);
          reboot();

          //Show time since last boot in milliseconds

        } 
        else if (cmd("uptime")) {

          unsigned long time = millis();
          Serial.println("Uptime: "+String(time));

          //Input string does not have any registered command

        }
        else {

          Serial.println(" command not found->"+inputString);

        }

        //Add the command to "history"
        lastcmd = inputString;

        //prepare for next command
        inputString = "";
        stringComplete = false;
        Serial.print("Arduino:");

      }

      //The main loop function

      void loop() {

        serialEvent();
        if (stringComplete) {

          //Call our input handler function

          check_input(inputString);

        }
        digitalWrite(13,ledstate);

      }

      //This function works when we have data comming from the serial port

      void serialEvent() {

        while (Serial.available()) {

          char inChar = (char)Serial.read();
          // [ Backspace ]

          if ( inChar == '\b') {

            //inputString.remove(inputString.length() - 1, inputString.length());
            Serial.print(' ');
            Serial.print('\b');

          }
          // [ Enter ]
          else if ( int(inChar) == 13 ) {

            inChar = '\n';

          } 
          else {

            //add current character to input command

            inputString += inChar;

            //Serial.print(int(inChar)); //debug control characters

          }

          if (inChar == '\n') {

            stringComplete = true;

          }

        }

      }


    

A snapshot of the program running

 Serial Arduino Commands' capture

It was strange to have the message printed on the tail terminal, not immediately when it was executed, but when then next command was executed. In the Arduino IDE serial console, the message was printed immediately.

On Debian 9.0.3 (testing) 64 bit, the TeleKIT serial port was recognized but it was not possible to connect to it via the Arduino IDE. An error popped up when opening the Tools menu (regardless of wether there was a board connected to the USB port or not). The message was:

	
	  java.lang.NullPointerException thrown while loading gnu.io.RXTXCommDriver
	
      

Nevertheless, once the board was programmed on another computer, the board could communicate via the console. It is important to mention that the port has problems with communication if the speed is not the same on the board and on the console. It was possible for me to program the serial port speed only via the Arduino IDE.

With an update via

	
	  sudo apt update
	  sudo apt upgrade
	
      
and then using Arduino IDE via the Fritzing Interface, the port was recognized by the Arduino IDE. Perhaps it is something else I did.

Group assignment with Mods

In order to make an interface in Mods we made a group assignment to create a gears of the desired number of teeth and export to a CNC millable file.

First we chose program on the right buton actived menu:  falta bildo

Then we chose the current server to select the program from:  falta bildo

The program we chose was the one that generates Gcode for milling from a PNG file source:  falta bildo

So the program in javascrip was loaded on the web page:  falta bildo

Then selected on an empty space the new program to insert:  falta bildo

Chose the server as the source of the program again:  falta bildo

Selected the program that generates a gear in PNG file from data we enter on the input boxes:  falta bildo

So the program appeared at the top of the window. But we moved the 3 mods of the program to a free space:  falta bildo

We removed the involute rack module from the gears program which we did not need any more. Then we placed them close to the part where their output would feed the inputs of our Gcode generation program. Last we added the size module in order to have the image info output as needed by the mill raster 2D module from the Gcode generating program:  falta bildo

We removed read PNG module from the gears program which we did not need any more. And we finally linked the outputs to the inputs as follows:

 falta bildo

So now we can parametrically generate a gear in Gcode. Then we can save the program for local use by selecting programs and the save local program (from the menu activated by the right mouse button). We can access this program with the modifications and the default parameters we saved it with on the browser without connecting to the server.

Best solution for interface: Ruby Shoes

Ruby Shoes is a language for creating window applications what will run on any brand of desktop. It is very simple to write applications with. Here is the program of a test application I made for fun.

 falta bildo  falta bildo  falta bildo  falta bildo  falta bildo
      # coding: utf-8
      # Copyright 2019 Quiliro Ordonez
      # GNU AGPLv3

      Shoes.app(:title => "History Lesson", :height => 150, :width => 300) do
        stack do
          @p = para
        end
        flow do
          button("1800s") { @p.replace "The eighteen hundreds were the time of the industrial revolution. It brought the power of machinery to fabrication. This provided great multiplication of production capacity." }
          button("1900s") { @p.replace "The nineteen hundreds had great use of hidrocarbons to increase production even more. They also allowed the proliferation of computers." }
          button("2000s") { @p.replace "The twenty hundreds gave rise to nano- and bio-technology." }
          button("2100s") { @p.replace "The twentyone hundreds will be the era of unlimited life expectancy." }
        end
      end	

      # Alternative process to run this same application.-
      # Opening Shoes IRB (interactive interpreter) -> Alt + = 
      # Commands entered:
      #app = Shoes.app(:title => "History Lesson", :height => 75, :width => 300) {}
      #app.stack { @p = app.para }
      #f = app.flow { app.button("1800s") { @p.replace "Eighteen hundreds" } }
      #f.button("1900s") { @p.replace "Nineteen hundreds" }
      #f.button("2000s") { @p.replace "Twenty hundreds" }
      #f.button("2100s") { @p.replace "Twentyone hundreds" }

      # Shoes script which does the same thing
      # to be run with .shoes/federales/shoes HistoryLesson.rb
    

Here is the Shoes History lesson practice exercise source code.

I have made an interface to manage the received data of my final project's receiver from the transmitted data of my final project's transmitter. So I point the transmitter to the receiver as per my final project. This receiver is connected to an FTDI to USB dongle. And the dongle is connected to the USB port on a computer.

 falta bildo

I must send the received data on my receiver to the USB port in my computer. Then the data should be handled by the user interface. I made a new program for my receiver which sends the received light data to the FTDI port.

 falta bildo  falta bildo

And I program the receiver with my In-System Programmer.

 falta bildo

The received light data on the receiver is sent to the computer USB port. And it is detected by a Ruby program on my computer.

        require "serialport"
        port_str = "/dev/ttyUSB0"
        baud_rate = 115200
        data_bits = 8
        stop_bits = 1
        parity = SerialPort::NONE

        sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity)
        while true do
         message = sp.gets
         if message
           message.chomp!

           puts message
         end
        end
    

In practice I could not make it work because the In-System-Programming port is destroyed.

My interface asks the user to order it to detect the incomming data. Then it pops up a window saying it is detecting the incomming data. When the interface detects 100 data received, it opens another window reporting such event.

This is the Ruby Shoes program for the user interface.

        Shoes.app {
          button("Start reading data") {
            
            require "serialport"
            port_str = "/dev/ttyUSB0"
            baud_rate = 115200
            data_bits = 8
            stop_bits = 1
            parity = SerialPort::NONE
            sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity)

            cuenta=0
            anterior=0
            actual=1
            
            while true do
              luz = sp.gets
              alert(luz)
              if luz > 100
                if anterior != actual
                  cuenta = cuenta + 1
                  anterior = actual
                end
              end
              if cuenta > 100
                alert("100 pulses received.")
              end
                # message.chomp!
                # puts message
            end
          }
        }
    

It works when not including the ruby serial port data detection when tested without the FTDI-to-USB dongle. Shoes shows a problem when including the SerialPort gem (a library). The SerialPort gem is used for communicating with the USB port via the Ruby language.

Another shoes interface

I have developed another interface for shoes because I thought I had not developed one.

      # GUI_send.rb
      # Copyright Quiliro Ordóñez 2019
      # GNU AGPLv3
      
      # coding: utf-8
      
      # Parameters for serial comunication via USB
      require "serialport"
      port_str = "/dev/ttyUSB0"
      baud_rate = 9600
      data_bits = 8
      stop_bits = 1
      parity = SerialPort::NONE 
      
      Shoes.app
      :title => "TeleKIT",
      :width =>450, :height => 50 
      do
        para "¿Cuál es tu mensaje?"
        @enviado = edit_line
        button "Enviar" do
          # Data sent to serial port.
          sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity)
          sp.print(@enviado,"\n", "\r")
          sp.close
          alert(@enviado.text, :title => "Enviado al otro terminal")
        end
      end
    

Here is the source code to the new Shoes app to communicate with TeleKIT.

When executing, I have a problem with the SerialPort library because apparently Shoes needs it to be loaded separately by way of its own configuration interface.

 falta bildo

So I commented out the parts of the Shoes program preamble. So it presents the initial window.

 falta bildo

But when I press the Send button. I have no result. When I press Alt + =, I see the errors on the console as displayed below. The other serial communication command could not be executed.

 falta bildo

Which is caused by this line:

sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity)

I think this can be repaired by including the serialport gem from the Configuration interface.

There is also an interactive Shoes terminal where you can test Shoes' commands realtime. It can be shown with Alt + /. And looks like this.

 falta bildo

You can also practice just Ruby on the Ruby terminal. Just type irb at the BASh terminal. You will get something like this.

 falta bildo

Regarding the firmware: the sending TeleKIT device must add this code to the existing one on the microcontroller.

      int incomingByte = 0;   // for incoming serial data

      void setup() {
        Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
      }
      
      void loop() {

        // send data only when you receive data:
        if (Serial.available() > 0) {
                // read the incoming byte:
                incomingByte = Serial.read();
          if(incomingByte=="0")
          {
            digitalWrite(led,0);
          }
          else
          {
            digitalWrite(led,1);
          }
   
        }
      }
    

Loading this code to the microcontroller is not possible because the ISP connections are destroyed. It is necessary to make a new PCB and resolder the electronics in order to make the software tests.

 falta bildo destroyed TeleKIT

But the device is positively detected as a USB device through the FTDI-to-USB dongle.

 falta bildo

And as /dev/ttyUSB0.

 falta bildo

So it is probable that the script works.

Sources

Scratch design file
Ruby program for receiving data on the USB port
Ruby Shoes program for the user interface
Arduino program to send the received light data via FTDI
new Shoes app source code to communicate with TeleKIT









Other photos

 falta bildo  falta bildo  falta bildo  falta bildo  falta bildo  falta bildo  falta bildo  falta bildo  falta bildo  falta bildo  falta bildo  falta bildo  falta bildo  falta bildo  falta bildo