Raspberry Pi ...and... PythonScratchBashNodeRedCjavaWolframCOBOLR ...and minecraft?

Raspberry Pi ...and... PythonScratchBashNodeRedCjavaWolframCOBOLR ...and minecraft?

My friend Helen Wall recently posted about the family tree of programming languages. There's 4,800 of them - probably more. Here's the article...

I've been exploring programming languages and the Raspberry Pi. I've especially been interested in languages that can be used to control the GPIO (General Purpose Input Output). I apparently have a lot of free time, so here's a collection of those languages - and a snippet of each below...

What are your thoughts? Have you used any of these with the Raspberry Pi?

Please subscribe to mnRRRRRRR for more #RaspberryPi goodness.

The Languages - demonstrations

Here's a collections of links to LinkedIn videos for each language, showing how it works with Raspberry Pi

: Python : Scratch : bash : Node-Red : C : java : Wolfram : COBOL : Minecraft : R : BASIC :

The Languages - snippets

Python

# example of programming Raspberry Pi GPIO with gpiozero
# refer to gpiozero.readthedocs.io

import gpiozero as gpzero
from time import sleep

# set up pushbutton and bank of leds
resetbutton = gpzero.Button(3)
leds = gpzero.LEDBoard(26,16,20,21)

# functions to control behavior
def LightsOn ():
    while resetbutton.is_pressed:
        leds.on()
    
def ResetCounter ():
    global counter
    leds.off()
    counter = 0
    
def binary2lights(showThis):
    leds.value = (
        showThis & 0b1000,
        showThis & 0b0100,
        showThis & 0b0010,
        showThis & 0b0001)
    
# setup button handlers    
resetbutton.when_pressed = LightsOn
resetbutton.when_released = ResetCounter

# send 0...15 to lights
while True:
    ResetCounter()
    while counter < 16:
        binary2lights(counter)
        counter += 1
        sleep(1)
    
    

Scratch

Scratch is a visual / block style language so there aren't any snippets. Here's a screen shot. This scratch code does the same thing as the python code listed above.

No alt text provided for this image

bash

Bash is often overlooked as a diminutive scripting language, only used by system administrators to automate daily tasks. With a Raspberry Pi, bash provides a quick and easy way to knock out a solution complete with GPIO support. The following BASH code does the same thing as the python and scratch code above.

#!/bin/bash

# the GPIO requires root level access. So...
# cd to exercise files
# then...
# sudo bash ./09-05_bash_gpio.sh

# bash shell script to demonstrate gpio control

# set up pushbutton
resetbutton=3 # BCM numbering scheme 
echo $resetbutton > /sys/class/gpio/export
echo "in" > "/sys/class/gpio/gpio${resetbutton}/direction"
echo "assign GPIO pin $resetbutton as pushbutton"

# set up bank of LEDs
# pin 26 is MSB. pin 21 is LSB
# so ${LED_pins[0]} points to gpio pin 21, which is least significant bit (LSB)
LED_pins=(21 20 16 26) # BCM numbering scheme. 
LED_paths=() # creating an array for use in a minute

# Assign GPIO pins to LEDs
for LED_idx in {0..3}
do
	echo "assign GPIO pin ${LED_pins[$LED_idx]} as LED"
	echo ${LED_pins[$LED_idx]} > /sys/class/gpio/export
	LED_paths[$LED_idx]="/sys/class/gpio/gpio${LED_pins[$LED_idx]}/"
	echo "out" > "${LED_paths[$LED_idx]}direction"
done

# create and install function to clean up pin assignments on control+c
echo "press CTRL+C to stop..."
function controlC {
	echo
	for LED_idx in {0..3}
	do
		echo "Clean up GPIO pin ${LED_pins[$LED_idx]}"
		echo ${LED_pins[$LED_idx]} > /sys/class/gpio/unexport
	done
	echo "Clean up GPIO pin $resetbutton"
	echo $resetbutton > /sys/class/gpio/unexport
	exit $?
}
trap controlC SIGINT

# function to turn on/off LEDs
function LightsOn ( ) {
	# $1 is the argument passed to LightsOn. i.e LightsOn($1)
	echo $(($1 & 2#0001)) > "${LED_paths[0]}value"
	echo $(($1 & 2#0010)) > "${LED_paths[1]}value"
	echo $(($1 & 2#0100)) > "${LED_paths[2]}value"
	echo $(($1 & 2#1000)) > "${LED_paths[3]}value"
}

# this is the working loop
while :
do
	counter=0
	while [ $counter -lt 16 ]
	do
		# test for pushbutton
		if [[ $(< "/sys/class/gpio/gpio${resetbutton}/value") == "0" ]]
		then
			LightsOn 15 # turn on all the LEDs
			while [[ $(< "/sys/class/gpio/gpio${resetbutton}/value") == "0" ]] 
			do
				echo "waiting while button is pressed"
			done
			counter=0 # restart the count from zero
			echo "The button is released"
		fi
		LightsOn $counter
		sleep 1
		((counter++))
	done
done


Node-Red

Another visual language. Node-red relies on javascript for the logic behind the blocks - but employs a visual editor to illustrate the program flow. And yes - you guessed it - this node-red code does the same thing as the above code examples.

No alt text provided for this image

C

C is the "mother of all languages" - although I would award that title to assembler. Here's another way to perform the same activity.

/* 09-07_c_gpio.c
 * 
 * Demonstration of controlling the Raspberry Pi GPIO with C
 * 
 * 1) install bcm2835 (https://www.airspayce.com/mikem/bcm2835/index.html)
 * 2) cd directory-containing-this-file
 * 3) compile ... gcc -o bincount 09-07_c_gpio.c -l bcm2835
 * 4) ./bincount
 * 
 * Author: Mark Niemann-Ross
 * https://linkedin.com/in/markniemannross
 */


#include <bcm2835.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>

/* set up bank of LEDs
 * BCM 26 is MSB. BCM 21 is LSB
*/
#define LED_1 RPI_V2_GPIO_P1_40 // aka BCM 21
#define LED_2 RPI_V2_GPIO_P1_38 // aka BCM 20
#define LED_4 RPI_V2_GPIO_P1_36 // aka BCM 16
#define LED_8 RPI_V2_GPIO_P1_37 // aka BCM 26
#define resetbutton RPI_V2_GPIO_P1_05 // aka BCM 3

void LightsOn( int lightMask ) {
    // bcm2835_gpio_write(PIN, HIGH); turns on a pin
    // HIGH = 1
    bcm2835_gpio_write(LED_1, lightMask & 1 );
    bcm2835_gpio_write(LED_2, lightMask & 2 );
    bcm2835_gpio_write(LED_4, lightMask & 4 );
    bcm2835_gpio_write(LED_8, lightMask & 8 );
}

void ctlcHandler( int sig) {
    LightsOn(0);
    bcm2835_close();
    exit(0);
}

int main(int argc, char **argv)
{

    if (!bcm2835_init())
      return 1;
      
    signal(SIGINT, ctlcHandler);

    // Set the LED pins to output
    bcm2835_gpio_fsel(LED_1, BCM2835_GPIO_FSEL_OUTP);
    bcm2835_gpio_fsel(LED_2, BCM2835_GPIO_FSEL_OUTP);
    bcm2835_gpio_fsel(LED_4, BCM2835_GPIO_FSEL_OUTP);
    bcm2835_gpio_fsel(LED_8, BCM2835_GPIO_FSEL_OUTP);
    
    // set the resetbutton to input
    bcm2835_gpio_fsel(resetbutton, BCM2835_GPIO_FSEL_INPT);
    //  with a pullup
    bcm2835_gpio_set_pud(resetbutton, BCM2835_GPIO_PUD_UP);

    
    int counter;

    while (1)
    {
	counter = 0;
	while (counter < 16 ) {
	    while ( !bcm2835_gpio_lev(resetbutton) ) {
		printf("reset button pushed\n");
		LightsOn(15);
		counter = 0;
	    }
			
	    LightsOn( counter );
			
	    counter++;
			
	    delay(1000);
	}
    }
}

java

Java has been in the top ten most-used languages for years (for ever?) Here's the same process as above - coded with java.

        // provision gpio pin #09 as an input pin with its internal pull up resistor enabled

        final GpioPinDigitalInput resetButton = gpio.provisionDigitalInputPin(RaspiPin.GPIO_09, PinPullResistance.PULL_UP);


      led1 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_29, PinState.LOW);
      led2 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_28, PinState.LOW);
      led4 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_27, PinState.LOW);
      led8 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_25, PinState.LOW);


        resetButton.addTrigger(new GpioCallbackTrigger(new Callable<Void>() {
                public Void call() {
                        while(resetButton.isLow()) {
                                System.out.println("button pressed");
                                turnLightsOn(15);
                                lightCounter = 0;

                        } 
                        turnLightsOn(0);
                        return null; 
                        }
                } ));



        while(true) {
                lightCounter = 0;
                while (lightCounter < 16 ) {
                        turnLightsOn(lightCounter);
                        Thread.sleep(1000);
                        lightCounter++;
                }
        }



    public static void turnLightsOn(int lightMask) {
        // 0 <= lightMask < 16 ... the number to represent in binary
        System.out.println("turnLightsOn: " + lightMask);


        led1.setState( (lightMask & 1) > 0 );
        led2.setState( (lightMask & 2) > 0 );
        led4.setState( (lightMask & 4) > 0 );
        led8.setState( (lightMask & 8) > 0 );

    }


Wolfram

led1=21
led2=20
led4=16
led8=26

resetbutton=3

DeviceConfigure["GPIO", {
  led1->"Output", 
  led2->"Output",
  led4->"Output",
  led8->"Output",
  resetbutton -> "Input"
  }]



turnlightson[lightmask_]:= (
  Print["lightmask is ",lightmask];
  DeviceWrite["GPIO", led1 -> Boole[BitAnd[lightmask,1]>0]];
  DeviceWrite["GPIO", led2 -> Boole[BitAnd[lightmask,2]>0]];
  DeviceWrite["GPIO", led4 -> Boole[BitAnd[lightmask,4]>0]];
  DeviceWrite["GPIO", led8 -> Boole[BitAnd[lightmask,8]>0]]
  )


  DeviceWrite["GPIO", ...


led1 -> Boole[BitAnd[lightmask,1]>0]];

counter=0;

Do[

 (
  counter=0;
  While[counter<16,
   (

   While[DeviceRead["GPIO", resetbutton][resetbutton]==0,
     (
      turnlightson[15];
      counter=0;
      )

     ];

    
turnlightson[counter];
    counter++;
    Pause[1];


COBOL

 IDENTIFICATION DIVISION.
       PROGRAM-ID. RPIwithCOBOL.


       DATA DIVISION.
       WORKING-STORAGE SECTION.
        01 WS-GPIO-INIT PIC x(40) VALUE 'echo "21" > /sys/class/gpio/export'.
        01 WS-GPIO-DIR PIC x(50) VALUE 'echo "out" > /sys/class/gpio/gpio21/direction'.
        01 WS-GPIO-ON PIC x(40) VALUE 'echo "1" > /sys/class/gpio/gpio21/value'.
        01 WS-GPIO-OFF PIC x(40) VALUE 'echo "0" > /sys/class/gpio/gpio21/value'.
        01 WS-GPIO-ClR PIC x(40) VALUE 'echo "21" > /sys/class/gpio/unexport'.        
        
        PROCEDURE DIVISION.
        display "This is COBOL running on a Raspberry Pi".
        display "Here's how to call GPIO from COBOL".
        CALL "SYSTEM" USING WS-GPIO-INIT.
        CALL "SYSTEM" USING WS-GPIO-DIR.
        PERFORM FLASH-LITE 3 TIMES.
        CALL "SYSTEM" USING WS-GPIO-CLR.
        STOP RUN.
   
        FLASH-LITE.
        CALL "SYSTEM" USING WS-GPIO-ON.
        display "LED is ON".
        CALL "C$SLEEP" USING 1.
        CALL "SYSTEM" USING WS-GPIO-OFF.
        display "LED is OFF".
        CALL "C$SLEEP" USING 1.
           
        END PROGRAM RPIwithCOBOL.

Minecraft

So - why is minecraft part of a programming language overview? Because you can control the GPIO with minecraft. Here's how...

# example code for raspberry pi portal
# assumes a button for GPIO
# thanks to https://www.stuffaboutcode.com/p/minecraft-api-reference.html

from mcpi import minecraft, block, vec3
import gpiozero
from colorzero import Color
from time import sleep
from signal import pause

mc = minecraft.Minecraft.create()
led = gpiozero.RGBLED(red=21, green=20, blue=16)
button = gpiozero.Button(26)

class portalStateObject:
    
    oneDefined  ?= False
    twoDefined = False
    
    # keeps track of the state of two portals.
    # try if (portalState.oneDefined): etc
    def __init__(self):
        self.oneDefined = False
        self.twoDefined = False
    
    def setPortal(self, portalNumber, trueOrFalse):
        if (portalNumber == 1):
            self.oneDefined = trueOrFalse
        elif (portalNumber == 2):
            self.twoDefined = trueOrFalse
        else:
            raise ValueError("setPortal only accepts values for 1 or 2")

class portal:
    def __init__(self, thePortalNumber, theColor):
        self.portalNumber = thePortalNumber
        self.portalPosition = vec3.Vec3(0,0,0)
        self.color = theColor
        portalState.setPortal(self.portalNumber, False)
        self.portalAlert("Ready to create portal {}".format(self.portalNumber), theColor = 'white')
        
    def createPortal(self):
        # Create a portal at current position
        x,y,z = mc.player.getPos() # get current player position
        self.portalPosition = vec3.Vec3(x-2, y, z)
        mc.setBlock(self.portalPosition, block.GLOWSTONE_BLOCK.id ) # complete list of block types at https://www.stuffaboutcode.com/p/minecraft-api-reference.html
        self.portalAlert("{}: Created portal {}".format(self.color, self.portalNumber))
        
    def deleteThisPortal(self):
        # this would be useful
        pass
    
    def amIHere(self):
        x,y,z = mc.player.getPos()
        if (int(self.portalPosition.x - 1) <= int(x) <= int(self.portalPosition.x + 1) and
            int(self.portalPosition.y - 1) <= int(y) <= int(self.portalPosition.y + 1) and
            int(self.portalPosition.z - 1) <= int(z) <= int(self.portalPosition.z + 1 ) ):
            return(True)
        else:
            return(False)
        
    def goHere(self):
        # go to this portal
        mc.player.setPos(self.portalPosition.x + 2, self.portalPosition.y, self.portalPosition.z)
        self.portalAlert("Returned to portal {}".format(self.portalNumber), theColor = 'orange')
        
    def portalAlert(self, theMessage, theColor = 'tbd'):
        # message to chat, change LED to this portal color
        if (theColor == 'tbd'):
            theColor = self.color
        mc.postToChat(theMessage)
        led.pulse(on_color = Color(theColor))
    
# set up objects

portalState = portalStateObject() # create an object we can use to track portal state

portalOne = portal(1, "blue")
portalTwo = portal(2, "red")

def buttonHandler():
    if (not portalState.oneDefined):
        portalOne.createPortal()
        portalState.setPortal(1, True)
    elif (not portalState.twoDefined):
        portalTwo.createPortal()
        portalState.setPortal(2, True)
    else:
        portalOne.goHere()

button.when_pressed = buttonHandler

# start watching minecraft
while True:
    if (portalOne.amIHere()) : portalTwo.goHere()
    if (portalTwo.amIHere()) : portalOne.goHere()
    print("Here: {}, portalOne: {}, portalTwo: {}".format(mc.player.getPos(), portalOne.portalPosition, portalTwo.portalPosition) )
    sleep(1)
    
pause()

R

# assign buttons
btnAlpha <- 15 # BCM numbering scheme
btnGamma <- 14
LEDred <- 9
LEDblue <- 10
LEDgreen <- 11


while (doExampleOne) {
	getGPIOcmd <- paste("gpioget gpiochip0", btnAlpha)
	if (system(getGPIOcmd, intern = TRUE) == 0) {
		print("Alpha")
		setGPIOcmd <- paste0("gpioset --mode=time --sec=1 gpiochip0 ", 
							LEDred,"=", sample(0:1,1), " ",
							LEDblue,"=", sample(0:1,1), " ",
							LEDgreen,"=", sample(0:1,1))
		print(setGPIOcmd)
		system(setGPIOcmd)
	}
	getGPIOcmd <- paste("gpioget gpiochip0", btnGamma)
	if (system(getGPIOcmd, intern = TRUE) == 0) print("Gamma")


}
# control-Z stops the loop
		



BASIC

REM credit to Richard Thomas Russell, creator of BBC BASIC. 
REM https://www.rtrussell.co.uk
REM details at https://www.raspberrypi.org/forums/viewtopic.php?t=175703
REM based on code at https://elinux.org/RPi_GPIO_Code_Samples#Direct_register_access



      INSTALL @lib$ + "gpiolib"
      INSTALL @lib$ + "stringlib"


      gpio% = FN_gpio_setup


      FOR pin% = 9 TO 11
        PROC_gpio_inp(gpio%,pin%)
        PROC_gpio_out(gpio%,pin%)
      NEXT pin%


      previous% = %111110000000

      FOR pattern% = %000000000000 TO %111111000000 STEP %10000000
        PROC_gpio_clr(gpio%, (pattern% EOR previous%) AND NOT pattern%)
        PROC_gpio_set(gpio%, (pattern% EOR previous%) AND pattern%)
        previous% = pattern%
        WAIT 20
        PRINT FN_tobase(gpio%!&34 >> 7 AND %11111, 2, 5)
      NEXT pattern%


      PROC_gpio_clr(gpio%, %111111000000)

      PRINT "Finished"


What are your thoughts? Which language do you use most often? Have you used any of these to control the Raspberry Pi?

Helen Wall

LinkedIn [in]structor | Data Science Consulting

3 年

Thanks for the shout-out Mark Niemann-Ross!

Nice work! I suspect ABAP is like Finnish, a strange syntax and language that does not correspond to any know patterns. ??

要查看或添加评论,请登录

Mark Niemann-Ross的更多文章

  • Documenting My Code ... For Me

    Documenting My Code ... For Me

    There are two signs of old age: old age, and ..

  • R Meets Hardware

    R Meets Hardware

    R is a programming language for statistical computing and data visualization. It has been adopted in the fields of data…

    2 条评论
  • Party Buzz Kill: modifying data

    Party Buzz Kill: modifying data

    So Steve (SQL), Marsha (C), Bob (Python), and I (R) are at this party. We have TOTALLY cleared the room, especially now…

    2 条评论
  • Rain - Evapotranspiration = mm Water

    Rain - Evapotranspiration = mm Water

    "Eeee-VAP-oooo-TRANS-PURR-ation," I savor the word as I release it into our conversation. I'm still at the party with…

  • Party Buzz Kill: Data Storage

    Party Buzz Kill: Data Storage

    I'm at this party where Bob and Marsha and I are discussing the best languages for programming a Raspberry Pi. Bob…

    5 条评论
  • R Waters My Garden

    R Waters My Garden

    I'm at a party, and the topic of programming languages comes up. A quarter of the room politely leaves, another half…

    10 条评论
  • Caning and Naming

    Caning and Naming

    We've been back from Port Townsend for a week. Progress on the boat isn't as dramatic as it is when we're spending the…

    1 条评论
  • Irrigate with R and Raspberry Pi

    Irrigate with R and Raspberry Pi

    I’m working on my irrigation system. This requires a controller to turn it on and off.

    3 条评论
  • 5 Reasons to Learn Natural Language Processing with R

    5 Reasons to Learn Natural Language Processing with R

    Why learn R? Why learn Natural Language Processing? Here's five reasons..

    1 条评论
  • Performing Natural Language Processing with R

    Performing Natural Language Processing with R

    I recently released a course on Educative covering topics in Natural Language Processing. Different Learners -…

    1 条评论

社区洞察

其他会员也浏览了