Raspberry Pi

RaspberryPi ' is a single-board computer.

See Also

Raspberries , by Jean-Claude Wippler, 2012-06-24

Vendors

Farnell
Allied Electronics , North America
Adafruit , North America
RS Components , UK
buyapi.ca , Canada

Description

dzach: Tcl/Tk 8.5 is very easy to install on Raspberry Pi:

sudo apt install tcl8.6
sudo apt install tk8.6

or one can try compile tcl8.6 for it.

Be aware that some distributions create version specific binaries like tcl8.6 and wish8.6 (or tcl86 and wish86) so try those if tclsh and wish are not found.

Together with a Gertboard it will be a nice playground for Tcl/Tk.

Using GPIO from Tcl: WiringPi-Tcl


RS 2013-09-27: Got my Pi running, and guess what: Tcl/Tk 8.5.11 are already included in Raspbian ;^)

% parray tcl_platform
tcl_platform(byteOrder)   = littleEndian
tcl_platform(machine)     = armv6l
tcl_platform(os)          = Linux
tcl_platform(osVersion)   = 3.6.11+
tcl_platform(platform)    = unix
tcl_platform(pointerSize) = 4
tcl_platform(threaded)    = 1
tcl_platform(user)        = pi
tcl_platform(wordSize)    = 4

Also tested as local WLAN webserver with Playing CGI - works well and fine. One must be superuser to open port 80, so

$ sudo tclsh dustmoteplus.tcl

Rildo Pragana 2013-04-02 20:03:30:

I needed a tclkit for it, so using kitgen I was able to generate one. If you need, here is a small github project with the binaries ready to run: [L1 ] Tested on a Raspbian, you may get the image at [L2 ]


RFox 2012-06-29 18:47:16:

Mine is on order I can keep people posted. The project we have in mind is to get it to serve a special purpose set of USB data acquisition devices on the net. Yes I know there are ethernet USB extenders but we want a bit more smarts on top of the device.


Mysund 2012-07-03 12:52:11:

Tcl on the Raspberry PI...

This sounds indeed as a very nice thing.

It can actually be a very nice hw-platform to promote Tcl in these Tcl slow times.

If i get the time/energy, i might make some short tutorials for Tcl.


MLai 2012-11-08:

The image 2012-10-28-wheezy-raspbian.zip already includes Tcl/Tk8.5. Socket communications seem to work fine, for (a) tcl socket client and server on the RasPi, and (b) tcl socket server on RasPi and tcl socket client on another Linux machine.


Gerhard Reithofer 2013-02-17:

As opposed to Gordon's WiringPi-Tcl as binary extension, I've created a Tcl-only library for controlling the General Purpose Input/Output ports from Tcl. It uses the /sys/ pseudo-filesystem to program the ports direction (input or output) and reading from the ports or write values to it.

# raspi2.tcl --
#   Raspberry Pi GPIO-Interface 
# 
# Contents: Interface to control the GPIO ports of the Raspberry Pi.
# Date: Sat Feb 17, 2013
#
# Abstract:
#   A tcl-only library for controlling the General Purpose In/Out ports
#   of the credit-card-sized single-board computer Raspberry Pi.
#   See: http://www.raspberrypi.org/
#
# Remark:
#   Please keep in mind, that usually only root is allowed to
#   read and write IO ports.
#
# COPYRIGHT AND PERMISSION NOTICE
#
# Copyright (C) 2013-02 Gerhard Reithofer <[email protected]>.
#
# All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, and/or sell copies of the Software, and to permit persons
# to whom the Software is furnished to do so, provided that the above
# copyright notice(s) and this permission notice appear in all copies of
# the Software and that both the above copyright notice(s) and this
# permission notice appear in supporting documentation.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
# OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
# INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# Except as contained in this notice, the name of a copyright holder
# shall not be used in advertising or otherwise to promote the sale, use
# or other dealings in this Software without prior written authorization
# of the copyright holder.
#
# Functions:
#   open_port $port $dir
#     Opens a GPIO port for reading (in) or writing (out): open_port 14 "out"
#   close_port $port
#     Closes an open port: close_port 14
#   write_port
#     Write a value (typically 0 or 1) to a GPIO: write_port 14 1
#   read_port
#     Read a value from a GPIO: set result [read_port 14]
# 
# Variables:
#     raspi2::debug       - enable/disable debugging output, def. 0
#     raspi2::raspi_rev   - define Raspberry Rev. (1 or 2), def. 2
#     raspi2::port_check  - enable/disable "valid port" checking, def. 1
#     raspi2::valid_ports - defines "valid ports" list depending on
#                           the setting of $raspi2::raspi_rev 
#
# Known bugs:
#   IO errors are not trapped inside the library.
#

package provide raspi2 0.1

namespace eval raspi2 {
  
  variable debug 0
  variable sys_path "/sys/class/gpio"
  variable direction
  
  variable port_check 1
  # Use tcl command
  #    set raspi2::port_check 0
  # for disabling "valid port checking" (runtime costs)
  
  variable raspi_rev 2
  # I use Rasperry Pi  Rev. 2 as default, use tcl command
  #    set raspi2::raspi_rev 1
  # for Rasperry Pi  Rev. 1
  
  # *** Raspberry Pi Rev. 1 + 2 "valid port" definitions
  # Ports reference: http://elinux.org/RPi_Low-level_peripherals
  variable valid_ports
  array set valid_ports {
    1 {0 1 4 7 8 9 10 11 14 15 17 18 21 22 23 24 25}
    2 {2 3 4 7 8 9 10 11 14 15 17 18 22 23 24 25 27}
  }

  # DEBUG output function
  proc debug_out {s} {
    variable debug   
    if {$debug} {
      puts "DEBUG: $s"
    }
  }
  
  # aux function to construct the direction port path
  proc direction_port {port} {
    variable sys_path
    
    set dir_port [file join $sys_path "gpio$port" "direction"]
    debug_out "direction_port $port => $dir_port"
    
    return $dir_port
  }
  
  # aux function to construct the value port path
  proc value_port {port} {
    variable sys_path
    
    set val_port [file join $sys_path "gpio$port" "value"]
    debug_out "value_port $port => $val_port"

    return $val_port
  }
  
  # internal - make port (un)accessible by (un)exporting
  proc activate_port {port {onoff "off"}} {
    variable sys_path
    
    if {![string is boolean $onoff]} {
      error "activate_port: parameter 'onoff' must be boolean"
    }
    if {$onoff} {
      set act_port [file join $sys_path "export"]
    } else {
      set act_port [file join $sys_path "unexport"]
    }
    put_line $act_port $port
    set portd [direction_port $port]
    set rval [file exists $portd] 
    debug_out "activate_port $port $onoff => $rval"

    return $rval
  }
  
  # aux function - read line from pseudo file ...
  proc get_line {path} {
    
    set inpf [open $path {RDONLY}]
    set line [gets $inpf]
    close $inpf
    debug_out "get_line $path => $line"
 
    return $line
  }
  
  # aux function - write line to pseudo file ...
  proc put_line {path line} {
    
    set outd [open $path {WRONLY}]
    puts $outd $line
    close $outd
    debug_out "put_line $path => $line"
  
    return $line
  }
  
  # exported - activate port for in/out
  proc open_port {port dir} {
    variable sys_path
    variable raspi_rev
    variable port_check
    variable valid_ports
    
    if {$port_check && [lsearch $valid_ports($raspi_rev) $port]<0} {
      set plist [join $valid_ports($raspi_rev) {, }]
      error "open_port: invalid port number '$port', valid are $plist"
    }
    if {$dir ne "in" && $dir ne "out"} {
      error "open_port: invalid port direction '$dir', valid is 'in' and 'out'"
    }
    
    set portd [direction_port $port]
    if {![file exists $portd]} {
      activate_port $port "on"
    }
    
    if {![file exists $portd]} {
      error "unable to initialize port communication"
    }
    
    set adir [get_line $portd]  
    if {$adir eq $dir} { 
      debug_out "port $port already set to '$dir'"
    } else  {
      debug_out "portd $portd present - (re)using it"
      put_line $portd $dir ;# it appears this is wrong, and should always output the direction in both parts of this if block 
    }
    
    set line [get_line $portd]
    debug_out "open_port $port $dir => $line"
   
    return $line
  }
  
  # exported - deactivate port for access
  proc close_port {port} {
    variable sys_path
    
    set portc [activate_port $port "off"]
    set res [file exists $portc]
    debug_out "close_port $port => $res"
  
    return $res
  }
  
  # exported - write value (0|1) to specific port 
  proc write_port {port value} {
    variable sys_path
    
    set outf [value_port $port]
    if {![file exists $outf]} {
      error "cannot not set port '$port' for writing '$value'"
    }
    
    put_line $outf $value
    set line [get_line $outf]
    debug_out "write_port $port $value => $line"
   
    return $line
  }
  
  # exported - read value from specific port (receive 0|1)
  proc read_port {port} {
    variable sys_path
    
    set inpf [value_port $port]
    if {![file exists $inpf]} {
      error "cannot not get port '$port' for read value"
    }
    
    set line [get_line $inpf]
    debug_out "read_value $port => $line"
   
    return $line
  }

  # direction_port, value_port, activate_port, get_line, put_line -- not exported
  namespace export open_port close_port write_port read_port
}

if {1 & [info script] eq $argv0} {
  set port  23
  set long  300
  set short 100
  set wait -300
  set morse {
   H . . . . E . L . _ . . L . _ . . O _ _ _ *
   R . _ . A . _ S . . . P . _ _ . I . . 2 . . _ _ _ }
  raspi2::open_port $port "out"
  foreach {sig} $morse {
    switch -- $sig {
      "."     { set delay $short}
      "_"     { set delay $long }
      default { set delay $wait }
    
    }
    if {[string is alnum $sig]} {
      set c $sig
    } else {
      set c [expr {$sig eq "*"?" ":""}]
    }
    puts -nonewline $c; flush stdout
    if {$delay>0} { raspi2::write_port $port 1 }
    after [expr {abs($delay)}]
    if {$delay>0} { raspi2::write_port $port 0 }
    after $short
  }
  puts ""
  raspi2::close_port $port
}

Don't forget, that usually ony the root user is allowed to read and write to hardware ports. So use 'sudo' or 'su' to run the scripts as root user, if you are not logged on as root.

Have much fun when controlling your hardware with the Pi - using Tcl,

Gerhard


sbron 2014-03-20:

Because I wanted more than just simple digital in- and output, I created a library called piio that can handle both gpio and i2c devices connected to one of the two i2c buses of the Raspberry Pi. The big advantage of using i2c is that it doesn't require root permissions. There are several i2c boards that can be used with the Raspberry Pi available from http://jeelabs.com/ .


TV 5-10-'14

It's a nice little Linux computer for minimum price, and it's got a lot of possibilities: I could even run Maxima, Fortran and such from this example [L3 ], except with very few blocks only, and connect a nice USB DA convertor to play notes from a MIDI USB keyboard ! It's also got a free copy of fullu functional Mathematica as atp install.


peterdh 29-08-15

The Syscomp software (www.syscompdesign.com) can be converted without much difficulty to run under Tcl/Tk on the raspberry pi. Has anyone recompiled the Img package for the Pi?


ET - 2017-01-30 01:10:48

It would appear that the above GPIO package needs to set the direction in ALL cases, even if it appears to have the value (in/out) already set. After an unexport, and a subsequent export, the direction setting will read out whatever was last written to it, however, that is not sufficient. At least this is how it works on my raspberrypi 4.4.38-v7+


Gerhard Reithofer 2017-02-23:

Yes, it's designed that way.

As shown in the "Morse-Code" writing example:

 raspi2::open_port $port "out"
 raspi2::write_port $port 1
 raspi2::write_port $port 0
 raspi2::close_port $port

or reading (no example given):

 open_port 14 "in"
 set result [read_port 14]
 close_port 14

Or do you mean another topic?


ET - 2017-03-03 04:55:24

Sorry, can't recall the error I was getting, or if it simply didn't light the led I was playing with. I finally just changed the code to always write the direction (on opening a port) even though the direction file was there and had a value. When I posed this on the pi message boards, they said you needed to set the direction always on startup. My impression was that this is needed to "kick" it going in addition to setting the direction. Since it's only done once on opening the port, it's not much of an extra step to set the direction. I just do this:

    if {$adir eq $dir} {
      debug_out "port $port already set to '$dir'"
    } else  {      debug_out "portd $portd present - (re)using it"
    }
    put_line $portd $dir ;# appears we need to set this regardless of the value there, as it must trigger something on the write

vh - 2019-02-20

Raspberrypi.org also sells a SenseHat plug-in board for the Raspberry Pi which includes an 8X8 LED matrix, a number of sensors (temp, pressure, magnetometer, gyroscope, accellerometer) and inputs like buttons and a tiny joy-stick. We've written a few scripts to learn how to interact with this device: https://github.com/vh3/tclSenseHat .


Just released w1 , a library to interact directly with 1-wire devices on the Pi. This uses the kernel modules, thus the pseudo FS under /sys for getting values. So far, there is only support for temperature measurements as the goal is to supervise a pool. The README includes how to connect a good temperature sensor that is immersible. EF


lai - 2020-03-08 19:04:07

Snack in Raspberry Pi 4 model B To install and test snack I follow these steps sudo apt-get install tclsh wish libsnack2-alsa sudo ln -s /dev/snd /dev/sound sudo ln -s /dev/dsp /dev/snd/dsp # reboot raspi 4 # Launch wish wish package require snack snack::sound snd # Download any wav file from internet snd read test.wav snd play


ZB - 2023-08-10 GPIO access via legacy sysfs interface has been deprecated since version 4.8 of the Linux kernel. The new way of doing GPIO is via the “descriptor-based” character device ABI (Application Binary Interface). The interface is exposed at /dev/gpiochipN or /sys/bus/gpiochipN where N is the chip number. Libgpiod (Library General Purpose Input/Output device) provides both API calls for use in your own programs and six user-mode applications to manipulate GPIO lines — I didn't try them yet, but it seems they will nicely cooperate with TCL scripts. More about this here