SCROLL

finalProject 0000 0001 CAD 0010 cutting 0011 programmer 0100 3Dprinting 0101 elecDesign 0110 makeBig 0111 embedProg 1000 moldCast 1001 inputs 1010 outputs 1011 networks 1100 machine 1101 interface 1110 wildcard 1111 notes

 

1110

Wildcard Week

DOCKER

 

 

For my wildcard week I decided to make my own wildcard topic as the organized options, while extremely interesting, didn't really fit into my final project. Instead I am going to figure out everything about Raspberry Pis, specifically how to deploy my programs to them and interact with its hardware.

 

 

Deployment to the RPi

Now that all my programs are written it's time to put them where they need to be. For the python script, that is on the RaspberryPi.

To do this I will use Docker. Docker is a software that allows you to package up your program and its environment into an isolated 'container'. Much like the virtual environment I set up on my Mac to write the OpenCV python script, the container will have everything my program needs to run and will keep all of its dependencies separate from everything that is not in the container. This means that a container can be run almost anywhere, hence your program can be run almost anywhere, regardless of the system or device's configuration.

What's a Docker Image? By Docker image I mean Docker container image. https://www.docker.com/resources/what-container

A google search for python opencv docker image returns this image as the second result. It'll do.

Here is a handy guide on how to get docker up and running on a RPi.

The OS I'm going to flash my Pi with is called Hypriot. It is the standard Pi Raspbian OS with Docker enabled. Raspbian and therefore Hypriot is a linux distribution.

Flashing Pi with Hypriot OS:

Resources:

https://blog.hypriot.com/getting-started-with-docker-and-mac-on-the-raspberry-pi/

https://computers.tutsplus.com/articles/how-to-flash-an-sd-card-for-raspberry-pi--mac-53600

Number following 'inet' in output

 

Can't find any good way to configure the pi to connect to my phone's hotspot. Going to download Hypriot's flash tool to refresh and edit network settings.

I refreshed, but just figured out I didn't need to. Instead, after flashing and unmounting the microSD, I unplugged it and plugged it back in. I edited a file called 'user_data' :

The important change was to the ssid and psk fields.

I rebooted the pi with my phone hotspot on and it connected! I can now wirelessly communicate with my pi.

To ssh into it I did the following:

Can also use

Which will just out put the IP (if connected via wifi)

Output:

It found two devices on the network. The first is my laptop and the second must be the pi. I ran ifconfig on the pi to confirm it was the same IP address.

I should be able to ssh to the pi from my Mac terminal now.

"pirate" is the host name of the pi as per the user_data file.

I used the default password "hypriot"

Result:

I'm in! Woohoo!

 

Resources for the above steps:

 

Getting a Docker Image with OpenCV and Python on the Pi

First I am making a Docker account.

The tutorial explains these commands

git clone https://github.com/docker/doodle.git // clones files to my mac

cd doodle/cheers2019 && docker build -t dmahon10/cheers2019 . // builds a docker image

docker run -it --rm dmahon10/cheers2019 // runs the image in a container

docker login && docker push dmahon10/cheers2019 // pushes to my docker hub account (like gitHub)

 

Read highlight below

  1. Clone docker image with openCV and Python3 to my mac

git clone https://github.com/janza/docker-python3-opencv.git

  1. Copy my program files and new docker image and files into same directory

  2. The directory should be good to go for a build. The next commands are:

    • docker build
    • docker push

    I am going to put them in one build_and_run.sh shell script file like so:

To make this file executable by terminal:

And execute it

At this point, I realized I had made a mistake

I was building an image with openCV and Python3. What I need to do is build an image with OpenCV, Python3 AND my app.

To do this, I need to write my own Dockerfile. A docker file includes instructions on how to build the image and what commands a user can use to run programs in the image.

Dockerfile Writing

Most docker files reference a parent file. The image I started building above is the image to be reference. This docker file looks like:

 

I noticed that this looked a lot like the commands I used to build OpenCV on my Mac. That's because it is doing the same thing.

My Dockerfile

Resource for writing docker files: https://stackify.com/docker-build-a-beginners-guide-to-building-docker-images/

I also now realize that I probably need an image made for Raspberry Pi. That is the janza/docker-python3-opencv image referenced above.

Running into this error:

Even after I login I get the same thing.

Realized I spelled the docker hub repo incorrectly in the Dockerfile. Should be:

Docker build, push, ssh and pull

 

Finished pulling.

In RPi terminal:

raspi-config

Then enable camera and allow reboot

Trying to run.

No dice

Trying to start container but it exits immediately

Trying docker run -it dmahon10/adversarial_chair:latest /bin/bash

Getting:

Some googling around and I find that this image is not compatible with the architecture of my Pi. The image was made for x86_64 but the pi is 64 bit quad core ARM architecture.

Searching for a made-for-pi python and OpenCV docker image

Here:

https://hub.docker.com/r/mohaseeb/raspberrypi3-python-opencv/

Changing my Dockerfile to:

Now to rebuild and push to my docker hub repo.

 

Having issues ssh ing so just pulled directly from pi.

Tried to execute the run command but got this error:

I didn't even think of adding this package to my image, so I have to go back now and do that. Rebuild, push and pull.

I have to do two things:

Good resource here: http://www.knight-of-pi.org/docker-container-with-rpi-gpio-access-for-the-raspberry-pi/

And here: https://raw.githubusercontent.com/JoBergs/RaspiContent/master/docker_GPIO/Dockerfile

https://github.com/JoBergs/RaspiContent/tree/master/docker_GPIO

New pull_and_run command

With the edits made I am executing the build_and_push.sh bash shell script.

Pulled it down onto my Pi, but got an error saying RPi.GPIO is not installed. Time to investigate.

 

Installing RPI.GPIO on Pi

I'm typing this up retroactively because it took me FOREVER to get this installed. I spent a couple hours rewriting my Dockerfile in different ways to have a RUN command that would install RPi.GPIO, but every time I got onto the Pi it would say package does not exist.

I also try pip install and apt-get from the command line on the pi. No dice.

I then started a virtual bash shell in my docker container on the pi to poke around and see what was installed.

From within this virtual shell, I ran apt-get python3-rpi.gpio and it would say already installed, yet when I tried to run my python script it would say it wasn't there. Furthermore, RPi.GPIO didn't show up with pip freeze or pydoc modules commands.

I then just ran sudo pip install RPi.GPIO and it installed it! Running pip freeze confirmed this.

Tried to run my python program videocv2.py , but got an error saying `

Which is great because it means it got past the import RPi.GPIO as GPIO line!

The error was thrown because I accidentally used GPIO.setmode() when I meant to use GPIO.setup() to make the pins outputs.

New Dockerfile:

 

Edits made to python script. Time to run ./scripts/build_and_push.sh

 

Its running! That is until there's a face in the frame...

I think it must be an issue with accessing the gpio pins.

Having --devices /dev/gpiomem should have done the trick, but I'm not so sure now.

Adding logs to my python script to check it out.

Build, push, pull, run...

 

Debugging

Logs show that starting off with no face in frame work as expected, but as soon as a face enters it gets stuck in this loop:

It never reaches the bottom if condition:

Just repeats this:

Over and over and over even when the camera is covered.

I realize my mistake was using a while loop rather than an if condition

However I did that because I wanted a constant pin HIGH signal from the Pi GPIO pin when the face was off center. If I use an if statement it will be turning on and off rapidly effectively doing PWM for the motor.

I will make it an if condition and retry.

Reran container on Pi. New error - video.open() needs an argument. I should have put 0 in.

I'm actually going to change this block to.

Build, push, pull, run.

IT WORKS!

The logs are showing that everything that supposed to happen is!

Now I need to check if the GPIO pins are actually firing.

I could use an oscilloscope, or just attach a couple LEDs to the pins to see if they flash.

I don't have an oscilloscope with me so LEDs it is.

Checking if GPIO pins firing

I'm using a bread board to connect some LEDs to the RPi's power and the GPIO pins I programmed.

 

I'm so close! Just need to make the DC motor board and connect it to the Pi!

 

Schematic in Eagle:

 

Traces:

 

 

Outline:

 

Board has been milled and soldered.

REGULATOR MISSING IN BELOW IMAGE

 

Programming Microcontroller

I need to get my C program running on the ATTiny micro-controller on the motor board.

To do this I need a programmer:

 

And a make file to get the C program ready for compiling.

To program the ATTiny microcontroller I will use AVRDUDE (AVR Downloader Uploader).

Makefile

Here is a good explanation of make files

These are the lines at the top of my makefile. They are the macros.

  1. Name of the file to compile
  2. Extension of the file to compile
  3. Microcontroller to program
  4. Frequency of the board to program

 

Complete Makefile

Ran make file. Lots of errors in my C code. Will correct now.

 

Correct C program

 

Full Test 1.0

Everything is hooked up and ready to roll. The photo just shows a mess of wires, but here's what's connected to what.

 

 

It works!

Kind off...

The motor just ticks when it should be turning. This is because of the on-off flickers as while loop iterates through the if blocks in my python program.

Here is the new program.

 

Make it presentable!

I want to have a live stream of what the camera is seeing displayed on my monitor so that it is easier to show what the program is actually doing. I will have to give the container the ability to access the Xserver of the RPi. Tips here

To do that I will add the below to my docker run command:

To the docker run command and remove the environment check before the cv2.imshow() line so that it will always show video output.

Try many different configurations of the above command options with no luck.

Did some more research and found that my RPi's OS, Hypriot, does not have X11 installed, so there is no way to display a GUI output.

https://github.com/hypriot/x11-on-HypriotOS

I'm following the below guide to installing X11 on my pi.

https://medium.com/@icebob/jessie-on-raspberry-pi-2-with-docker-and-chromium-c43b8d80e7e1

Went through all the steps and now I can't login to my Pi! Hoping I won't have to re-flash the pi.

 

Every time I put in my password, it seems to be loading something, but just returns to the login screen. No incorrect password message so it is definitely logging in, but it seems it doesn't know what to show once logged in or it is automatically logging out.

Luckily I can still ssh into the Pi from my laptop.

I will work to get the display up and running by the time I present but no promises that I'll be able to do that. I can at least run the program on my Mac which does show the video output.