Running Snap! Project locally on raspberry pi with gpio

Running Snap! locally on Rasberry pi or embedded in html with gpio support. Any Progress?

Hi All,
My first post so I hope this is in the right place.

I am trying to create a simulator to help teach electrical trade students PLC (programmable logic controller) programming. I am aiming to simulate various industry processes in snap!, converted to html? or embedded, with each part of a process controlled by the gpio pins. Eg. press button on screen and gpio turns on, pull gpio low and conveyor runs on screen etc.

I have read @cymplecy posts about scratchgpio and this seems like exactly what I need.
Has this ever been finalised? I’m not sure what commands to send or even how to send them. As the blocks used in the examples look like custom blocks.

ScratchGPIO was finished a long time ago - so long ago that it is now effectively obsolete :frowning:

It used a Python2 background program to bridge between Scratch 1.4 and the Pi GPIO pins.

Python2 is no longer supported in recent Raspberry Pi OS releases.

There is a workaround which is to run an old version of Raspbian (Stretch definitely still had Python2 support)

I was afraid of that as the posts were pretty old.
Is there a more current way using url block for example to send commands/requests? I would obviously have to set up a python web server of some description but it would only have to be specific to my task.

And then I guess would those functions still work if I embedded it or used xml?

PS. I feel like I’m talking to a celebrity after reading up on this stuff. :sunglasses:

If you KISS then a Python3 webserver, listening for HTTP requests, from Snap! ,to control the pins is an easy project

But if you then start to want to do other stuff , down the rabbit hole you'll go :slight_smile:

Pretty sure you can use a python web server, because you can make it listen to requests, and then you can control the pins directly in python. I think that might be the best solution right now.

This sounds like a great project. I'm not sure whether it would be suitable for emulating PLC programming, but we're currently using a Raspberry Pi Model 4b running Snap! communicating with a Raspberry Pi Pico microcontroller running MicroBlocks (https://microblocks.fun/). @jmaloney developed a library of Snap! blocks (Micro:Bridge) that enables Snap! to control physical objects using the Pico microcontroller. The Pico is only about five dollars and about the size of a stick of gum, so it works very well for our applications. This can all be run locally if necessary.

If this sounds like something that would be useful for your application, let us know and we can provide more details.

Thanks @glenbull , I think I may have been reading about the early days of your project.

This could definitely work to control i/o but I was hoping to run the snap! Pages on the pi so it can be a stand alone unit. The students program will be in an actual PLC hooked up to this pi through some interface relays etc. with either a mouse or touch screen to click buttons on the simulator. Beats building a bunch of pump systems or conveyor systems for them to hook up to.

Scratch3 offline has gpio functions now so I could use that I suppose, I was hoping to take advantage of the larger stage size in snap! But I’m not yet experienced with http and general web stuff. Good time to learn! :+1:

For us, Snap! is like Scratch on steroids. Both are good, but have different intended audiences and purposes. Snap! is very extensible, and we have gotten a lot of support from the Snap! community in developing extensions.

We would love to hear more as your project develops and will look forward to following its progress.

Scratch3 may be a viable route but my experience of it is it really needs a Pi4 with at least 2GB of RAM (I tried it on a 4GB one)

What I/O requirements do you envisage for your project? Are you just controlling relays or are you wanting to receive data as well?

I’m wanting to receive gpio inputs as well but in a pinch or to get started I toyed with the idea of just sending key presses from a python script, since my first simulation is running on ‘when key pressed’ blocks for testing purposes.

The trick was definitely getting gpio out to work.
I have set up a little web server using flask in python (not my own work) and that is working ok to control gpio from a web page, so I will now look at modifying it for my purposes. Just reading up on http to see what all the headers and data back and forth are.

Pi 4s are as rare as hens teeth at the moment.
Sorry if I drop off, I’m in Australia and we are about 10 hours ahead of UK. Let me know if you want me to send you the winning Loto numbers…. Is that how it works?

Soooo…

I’ve got a little web server up and running and controlling the gpio pin11.

I’ve just set it to receive http://pi ip address:port/11on or /11off and I can control it from chrome browser locally and over LAN. :sweat_smile:

The problem I have is when I try to put this in the url block minus http:// i get some gibberish and a 400 error http wrong version. I’m running offline snap!. My server reports v1.1 when it replies correctly to chrome. Is this obvious to anybody? Is http/1.1 still suitable? Cheers

Can you enable browser dev tools and see if any clues in the console log?

Are you running Snap! directly from a local folder or are you running a local webserver to serve files from your local folder?

Can you upload your webserver code (either here or elsewhere) and I'll try it out at my end?

I will try dev tools.

At this point I am running snap! offline from a folder on windows10 laptop on same network as pi. This python script that my Mate ChatGPT helped me write uses the built in webserver functionality of python 3 rather than the flask approach I started with. It actually did a really good job except for a few indexing errors that I had to debug.

import RPi.GPIO as GPIO
from http.server import BaseHTTPRequestHandler, HTTPServer

GPIO.setmode(GPIO.BOARD)
GPIO.setup([11, 12, 13, 15, 16, 18], GPIO.OUT)
#GPIO.setup(11, GPIO.OUT)

class RequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        path = self.path[1:]  # Remove leading '/'
        #print(str(path[:2]))
        if  len(path) < 4:
            print('length issue')
            self.send_error(404)
            return
        elif not path[:-3].isdigit():
            print('digit issue ' + str(path[:-3]))
            self.send_error(404)
            return
        elif int(path[:2]) not in [11, 12, 13, 15, 16, 18]:
            self.send_error(404)
            return
        pin = int(path[:2])
        print(pin)
        state = path[2:4] == "on"
        print (path[2:4])
        print(state)

        GPIO.output(pin, state)

        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        self.wfile.write(b"GPIO state set")

if __name__ == '__main__':
    server_address = ('', 8000)
    httpd = HTTPServer(server_address, RequestHandler)
    print('Server started')
    httpd.serve_forever()

I think I will change this in future to just recieve 8 bits to represent the outputs so I can update all outputs with one GET.

thanks @cymplecy looks like the url block is sending a https: request and I am set up for http: only?

Does anyone know an easy way to make snap! just send http? I really won't need encryption for local control.

This may shade some lights...

It's a good job @dardoro has a better memory than me :slight_smile:

Thanks @dardoro . I’ll try Firefox and see if the result is any better.

I won’t get a chance to do it tonight but maybe in the morning.

I'm having a play to see if using MQTT via websockets can bypass the issue.

Are you planning on running snap locally on the Pi eventually or are you going to stick to running it from a PC?

Hi @cymplecy ,

Don’t worry about it, it’s working!

So to clarify I can send url commands in both chrome and Firefox.

I had read somewhere that url block adds http:// to the start of whatever is entered. It seems as though this may be incorrect or perhaps I was reading about someone’s custom block. But by typing the whole url http://192.168.x.x:8000/11on or /11off it works with that web server script. Sorry for my noob late night brain not trying that straight away.