RPi: Building a Raspberry Shake seismogram on the Node-Red Dashboard

Goal:

Set up a real time Seismogram on the Node-Red Dashboard.

 

Resources:

Introduction:

After following the first tutorial on connecting  Shake to Node Red, now we can start to use Node-Red to process and visualize the seismic data that is being streamed through the UDP port.

Getting Started:

Before starting this tutorial, make sure you have already completed the “Streaming Raspberry Shake Data to Node-Red” tutorial. Your flow should look like this:

 

Make sure that there is UDP data being received by checking the debug tab. As you can see, the data coming through the Rshake Parser is still in object form, consisting of multiple types of information. For building the siesmogram graph, we just want the numerical data.

First, we have to add a switch node that discriminates the the channel of the data. If we are using a Shake 1D, it will be the channel EHZ. So, we must add a switch node after the parser, and format it to be listening for the property “msg.payload.channel” and underneath we can add the rule as: == “string” EHZ. This separates the data that we want.

The data is still not in a format useable for graphing, so we have to create a custom function node to separate the numerical data. Raspberry shake has created a code just for this purpose.

Go to the menu and choose import>clipboard, and paste this code and import the node.

[{"id":"299110c.a2af7f","type":"function","z":"d328b37.176a45","name":"format plot values","func":"\nvar EVERY_N_PACKET = 20; // max = 24\nvar POINTS_PER_SECOND = 100 / EVERY_N_PACKET;\nvar KEEP_SECONDS = 60;\nvar KEY=\"f2_all_points\";\n\nvar MAX_POINTS = POINTS_PER_SECOND * KEEP_SECONDS;\n\nvar input = msg.payload;\n\nvar data = [{series:[\"P\"],\n    data:[],\n    labels:[\"Points\"]\n}];\n\nvar allPoints = flow.get(KEY);\nif(allPoints == undefined)\n    allPoints = [];\n\n\nfor(var i=0, step=EVERY_N_PACKET; i + step < input.packets.length; i += step) {\n    var o = {x: input.ts + i*10,\n             y: input.packets[i]};\n    allPoints.push(o);\n}\n\nif(allPoints.length > MAX_POINTS)\n    allPoints = allPoints.slice(\n        allPoints.length - MAX_POINTS, \n        allPoints.length\n    );\n\nflow.set(KEY, allPoints);\n\ndata[0].data.push(allPoints);\n\n\nmsg.payload = data;\n\nreturn msg;","outputs":1,"noerr":0,"x":877,"y":171,"wires":[["73bf48a9.3fc398"]]}]

Connect the ‘format plot values” node to the switch node. Now, to finish we connect a Dashboard chart. Your flow should look similar to this:

Then, configure the chart in the way that you would like, and Deploy!

Now, open your local Node-Red Dashboard! You can access this page by entering your Node-Red address /ui. For example: http://10.18.102.253:1880/ui

Now, bang the table! Jump up and down! See what happens to the graph!

 

To continue working with the Shake Data in Node-Red, go to the next Tutorial!

Making a Shakemeter: https://t3alliance.org/rpi-building-a-shakemeter-with-raspberry-shake-and-node-red/

 

 

RPi Airquality Station: Creating an Animated Nyancat Wallpaper

 

Goal:

Use the RPi Airquality station hardware, combined with node-red to create an animated nyancat wallpaper

 

What you will learn:

Combining the basic LED Matrix nodes, with more advanced javascript nodes to create fancier output.

 

What you will need to know:

Getting started with node-red

 

Parts List:

  • Full RPi Airquality kit

Getting Started:

First step is to familiarize yourself with the ‘image’ node.

Drag one in from the ‘LED Matrix’ section of the palette and setup config node, if you haven’t got one ready to re-use

All of the display settings can be left at their default, but because we want the wallpaper to update quickly you can bump the ‘Refresh Delay Milliseconds’ down to 100.
By default the Matrix will only redraw all the objects on the screen 2 times a second, but with this setting changed it’s a more attractive 10 times a second.

Next we’ll inject an image in the matrix.

This is the animated NyanCat we’ll be using: https://t3alliance.org/wp-content/uploads/2019/01/nyanCat.gif
It’s a tiny image, about 20 pixels high; but that’s a good thing for us because it means it’ll actually fit on the display. If you wish to use your own gifs and images with this tutorials, be mindful that the LED Matrix that comes with the airquality kit is only 128×64 pixels, so you’ll have to manually resize most images you want to use with it.

Setup an inject node with the nyanCat url as the string, and connect it to the image node.Once you deploy, and inject the node you should see the image appear as pictured.

Notice that the nyanCat is not animated. The way the Image Node handles gifs, is that it increments the frame when injected multiple times. So if you press the inject node button again, you should see the next frame in the sequence appear. You can continue clicking all the way through until the image resets back to frame one.

Of course the Node-Red inject node comes with repeating functionality already, so all you really have to do is setup the inject node like this to see your nyanCat beautifully animated in the top corner.

 

Manually Moving NyanCat:

Next is the more complicated step of actually moving the image around; I’ll lay out the function nodes so you can copy and paste them if you get stuck.

The basis for all our functions will be this info that comes with the image node. By default you can inject a plain string that gets matched with the settings in the node, or you can send a fully featured object that contains data for where the image should be drawn, as well as what file it’ll be.

To start we’ll try send just the image itself, in a static location.

//create the message we'll output
var output = {}

//insert our properties into the payload
output.payload = 
{
    data: "https://t3alliance.org/wp-content/uploads/2019/01/nyanCat.gif",
    x: 10, 
    y: 10,
}

//send out to the next node
return output

Here’s what the function node looks like with the code inside:

On line 2 we setup an empty object that we’ll fill with our properties later.
Then on line 5 – 10 we setup our data, the url of the image, and the location.
Then finally we return the object we created at the start, which will output it from the node-output.

Hooked up to the Image node with a generic inject node, you can draw the nyanCat again, except this time it’ll be offset from the top corner by 10 pixels.
Play around with the values for X and Y to move it around the screen manually.

 

Autonomous Nyancat:

The next step is getting the X and Y to update automatically.

Luckily for us nyanCat only flies in a straight line, so the Y coordinate can remain static, only changing the X coordinate interests us.
Here is the new code:

//create the message we'll output
var output = {}

//setup our varaible for X
var location = flow.get("x") || 0

//check to see if we've went off the edge
if(location > 128) location = 0

flow.set("x", location + 1)


//insert our properties into the payload
output.payload = 
{
    data: "https://t3alliance.org/wp-content/uploads/2019/01/nyanCat.gif",
    x: location,
    y: 20,
}

//send out to the next node
return output

On lines 5 – 10 we work with a ‘flow’ variable, this named variable ‘x’ sticks around with the flow and allows the function node to ‘remember’ a value between injections.
First we save the current value into the ‘location’ variable. Then we check to see if ‘location’ is greater than 128; if it is we reset it to zero.
Finally we save the new location back into the ‘flow variable’. The rest of the function node is pretty much the same as the last one.

Now with this code setup, your nyanCat should fly from one side of the screen over and over again. Remember to setup the inject node to repeatedly inject instead of just when you press the button.

Here is an export of the flow so far, so you can catch up if you’re lost:

[{"id":"7a5afae4.690634","type":"image-to-matrix","z":"93c88281.18b06","name":"","file":"","xOffset":0,"yOffset":0,"matrix":"9b09c013.e6c5b","zLevel":"","x":900,"y":360,"wires":[]},{"id":"b4672224.50062","type":"function","z":"93c88281.18b06","name":"NyanCat Function","func":"//create the message we'll output\nvar output = {}\n\n//setup our varaible for X\nvar location = flow.get(\"x\") || 0\n\n//check to see if we've went off the edge\nif(location > 128) location = 0\n\nflow.set(\"x\", location + 1)\n\n\n//insert our properties into the payload\noutput.payload = \n{\n    data: \"https://t3alliance.org/wp-content/uploads/2019/01/nyanCat.gif\",\n    x: location,\n    y: 20,\n}\n\n//send out to the next node\nreturn output","outputs":1,"noerr":0,"x":680,"y":360,"wires":[["7a5afae4.690634"]]},{"id":"56d87a3a.4542c4","type":"inject","z":"93c88281.18b06","name":"","topic":"","payload":"","payloadType":"date","repeat":"0.1","crontab":"","once":true,"onceDelay":0.1,"x":440,"y":360,"wires":[["b4672224.50062"]]},{"id":"9b09c013.e6c5b","type":"led-matrix","z":"","height":"64","width":"64","chained":"2","parallel":"1","brightness":"50","refreshDelay":"100","mapping":"adafruit-hat-pwm","autoRefresh":true}]

Animated Bubbles:

As a finishing touch we’ll be adding some animated bubbles to the mix. These will just be circles with random position, size, and color.
Just like with the image node, we’ll be using the object definitions from the circle node.

Here is the code for generating a static circle, that just sits in the middle of the screen looking pretty.

var output = {}

output.payload = 
{
    radius: 10, 
    rgb: "255,0,0",
    x: 64, 
    y: 34
}

return output;

Note that it looks almost identical to the original, if you inject this straight into a circle node it’ll plant a big red circle in the middle of the screen. If you setup the nyanCat properly it should be flying past it a couple of times a minute.

Next we can setup the random location and color, both pretty complicated functions so don’t be scared to just copy and paste them.

//generate a random number between 0 to max
function randInt (max)
{
    return Math.floor(Math.random() * Math.floor(max));
}

//generate a random rgb color, using the randInt function
function randColor()
{
    return randInt(256) + ',' + randInt(256) + ',' + randInt(256);
}



var output = {}

output.payload = 
{
    radius: randInt(10), 
    rgb: randColor(),
    x: randInt(128), 
    y: randInt(64)
}

return output;

The most important concept to grasp here, is the calling of user made functions between lines 19 – 22.
Other than that not much has changed.

For the best style I copy and paste this node a few times, into their own seperate circle nodes.
That way nyanCat can fly through 3 bubbles instead of just 1

And here is the exported flow, to catch you up to the final project:

[{"id":"7a5afae4.690634","type":"image-to-matrix","z":"93c88281.18b06","name":"","file":"","xOffset":0,"yOffset":0,"matrix":"9b09c013.e6c5b","zLevel":"","x":900,"y":360,"wires":[]},{"id":"b4672224.50062","type":"function","z":"93c88281.18b06","name":"NyanCat Function","func":"//create the message we'll output\nvar output = {}\n\n//setup our varaible for X\nvar location = flow.get(\"x\") || 0\n\n//check to see if we've went off the edge\nif(location > 128) location = 0\n\nflow.set(\"x\", location + 1)\n\n\n//insert our properties into the payload\noutput.payload = \n{\n    data: \"https://t3alliance.org/wp-content/uploads/2019/01/nyanCat.gif\",\n    x: location,\n    y: 20,\n}\n\n//send out to the next node\nreturn output","outputs":1,"noerr":0,"x":680,"y":360,"wires":[["7a5afae4.690634"]]},{"id":"56d87a3a.4542c4","type":"inject","z":"93c88281.18b06","name":"","topic":"","payload":"","payloadType":"date","repeat":"0.1","crontab":"","once":true,"onceDelay":0.1,"x":440,"y":360,"wires":[["b4672224.50062","e5b23895.437f38","9f3dc778.1d1e98","202d83ef.c75e8c"]]},{"id":"50105316.5a64dc","type":"circle","z":"93c88281.18b06","name":"","xPos":0,"yPos":0,"radius":0,"rgb":"0,255,41","matrix":"9b09c013.e6c5b","zLevel":"","x":890,"y":300,"wires":[]},{"id":"e5b23895.437f38","type":"function","z":"93c88281.18b06","name":"Circle Function","func":"//generate a random number between 0 to max\nfunction randInt (max)\n{\n    return Math.floor(Math.random() * Math.floor(max));\n}\n\n//generate a random rgb color, using the randInt function\nfunction randColor()\n{\n    return randInt(256) + ',' + randInt(256) + ',' + randInt(256);\n}\n\n\n\nvar output = {}\n\noutput.payload = \n{\n    radius: randInt(10), \n    rgb: randColor(),\n    x: randInt(128), \n    y: randInt(64)\n}\n\nreturn output;","outputs":1,"noerr":0,"x":660,"y":300,"wires":[["50105316.5a64dc"]]},{"id":"4313edf2.721a04","type":"circle","z":"93c88281.18b06","name":"","xPos":0,"yPos":0,"radius":0,"rgb":"0,255,41","matrix":"9b09c013.e6c5b","zLevel":"","x":890,"y":260,"wires":[]},{"id":"9f3dc778.1d1e98","type":"function","z":"93c88281.18b06","name":"Circle Function","func":"//generate a random number between 0 to max\nfunction randInt (max)\n{\n    return Math.floor(Math.random() * Math.floor(max));\n}\n\n//generate a random rgb color, using the randInt function\nfunction randColor()\n{\n    return randInt(256) + ',' + randInt(256) + ',' + randInt(256);\n}\n\n\n\nvar output = {}\n\noutput.payload = \n{\n    radius: randInt(10), \n    rgb: randColor(),\n    x: randInt(128), \n    y: randInt(64)\n}\n\nreturn output;","outputs":1,"noerr":0,"x":660,"y":260,"wires":[["4313edf2.721a04"]]},{"id":"4863e929.52f748","type":"circle","z":"93c88281.18b06","name":"","xPos":0,"yPos":0,"radius":0,"rgb":"0,255,41","matrix":"9b09c013.e6c5b","zLevel":"","x":890,"y":220,"wires":[]},{"id":"202d83ef.c75e8c","type":"function","z":"93c88281.18b06","name":"Circle Function","func":"//generate a random number between 0 to max\nfunction randInt (max)\n{\n    return Math.floor(Math.random() * Math.floor(max));\n}\n\n//generate a random rgb color, using the randInt function\nfunction randColor()\n{\n    return randInt(256) + ',' + randInt(256) + ',' + randInt(256);\n}\n\n\n\nvar output = {}\n\noutput.payload = \n{\n    radius: randInt(10), \n    rgb: randColor(),\n    x: randInt(128), \n    y: randInt(64)\n}\n\nreturn output;","outputs":1,"noerr":0,"x":660,"y":220,"wires":[["4863e929.52f748"]]},{"id":"9b09c013.e6c5b","type":"led-matrix","z":"","height":"64","width":"64","chained":"2","parallel":"1","brightness":"50","refreshDelay":"100","mapping":"adafruit-hat-pwm","autoRefresh":true}]

To import, copy it into your clipboard; and come up to the ‘import’  menu here:

 

More Ideas:

As long as the file is the right dimensions you can use any animated gif for the display, here is another file you can link into the project in this tutorial.
https://t3alliance.org/wp-content/uploads/2019/01/original.gif

 

Another good resource is pixilart.com

Here you can create your own pixel art, set the exact size in pixels (useful for making sure everything fits on the display) and even export animated gifs.
To create a gif, use the layer tools on the right. This button duplicates your current layer which is useful for making slight changes on the next frame.Then use the ‘Download/Save’ tool to export your file as an animated gif.

RPi Node-Red: Uploading pictures to Google Photos

This tutorial is being worked on – the google photos node may not be working at this time due to changes in the underlying repositories. 

Goal:

Upload pictures from a node-red flow into a Google Photos folder.

What you will learn:

How to install and configure the easybotics-gphoto-upload node, and use it in your flow.

What you need to know:

Getting started with node-red

Parts List:

  • A raspberry pi setup with node-red
  • Raspberry pi camera

Getting Started:

  • First connect your camera to your raspberry pi while the power is off.
  • Power on your raspberry pi and make sure the camera is enabled in the configuration menu.
  • If it is not already installed you need to install the gphoto-upload node, because of some peculiarities with dependencies this node has to be installed manually, the procedure follows:

Copy and paste, or type these lines into a terminal window. If typing press enter after each line, if pasting in the whole block you should only need to press enter once.

cd ~/.node-red
sudo node-red-stop
sudo npm i node-red-contrib-easybotics-gphoto-upload
sudo npm i axios@^0.16.2

Then once that install is done(1-5min) copy and paste/type this line and press enter

sudo npm i axios@^0.16.2

Wait for this install to finish(1-5min)

Restart Node Red – you could type Start Node-Red into the terminal or click on the node red program link

Open a web browser and view 127.0.0.1:1880 – If you already had the web browser open refresh the node red page.

Node usage:

Drag the upload-photo node in from the palette, and enter the setup menu by double clicking on it.

It’s definitely a good idea to setup an entirely separate google account for use with node-red, rather than pasting your actual username and password into nodes; no matter how trusted.

To allow node-red to login to gphotos without two factor authentication, you must setup unsecured access here: https://support.google.com/accounts/answer/6010255

 

In the settings page, the filename and album can be set. Usually you would inject a filename, but if you inject an empty message it takes the defaults set here.

 

To setup the camera node, just make sure it’s set to output the filename.
And that the Image Resolution is set to anything other than the maximum.

Notes:

If you take pictures at the rate of once every 2 minutes here are the days you can expect before the 8GB of free space on the SD card is filled up:

Quality = 80

  • 2592×1944 – 2.7MB per photo = 3.5 days
  • 1920×1080 – 1.2MB per photo = 7 days
  • 1024×768 – 546KB per photo = 17 days
  • 320×240 – 96KB per photo = 98 days

If you need more space to keep the SD card from filling up quickly a larger 64, 128, or even 256GB card will store many more photos before filling up – do some math to figure out how many photos each can hold.

RPi Raspberry Shake: Setting up a raspberry shake NOOBS image

Goal:

Create a  raspberry shake SD card used to setup a raspberry-shake for the first time

Resources:

SD card, SD card reader, Raspberry Shake NOOBS zip: https://gitlab.com/raspberryShake-public/raspShake-SD-img/raw/master/raspishake-release.zip?inline=false

Introduction:

The raspberry shake is mostly a hands-off piece of hardware, it just needs to be assembled, plugged in and left alone. Though you might need to setup an SD card if your kit didn’t come with one, or you need a replacement. Once the card is written, the raspberry shake will install and configure itself as soon as it’s plugged in.

Preparing the SD card:

The raspberry shake installer needs the SD card to be formatted with a specific type of file system called FAT32, usually if you buy a blank SD card it comes pre-formatted like this; but if you’ve already used it for something its not a sure thing.

We’ll use a piece of software called gparted to format the SD card, so the first step is to install gparted with the following command:

sudo apt-get install gparted

next, from the same terminal run gparted as root:

sudo gparted


When gparted is open go to the top right of the window, and select your SD card from the drop down; a good hint is to look at the size in GiB. I know my SD card is 8GIb so its probably the one labeled ‘7.4Gib’ not the 16 Gib one.
Make sure to never edit /dev/mmblk0/ because this is probably the card your raspbian is running on.

One you have the sd card open, right click on all the partitions listed below, and select ‘delete’. Gparted only applies operations in a separate step, so even though we deleted the partitions here it won’t actually do anything until we hit apply later.

 

 

 

 

 

After deleting the old partitions its time to make a new one, right click in the area we deleted the old partitions from, and select new. All the settings can be left at their defaults except for changing the file system to ‘FAT32’ as pictured.

Next the last step is to hit ‘Apply’ which is the green trick button in the bar next to where we selected the SD card. When it asks you if you’re sure click ‘Apply’.

Formatting the SD card will take a few seconds, after its done you can close gparted and remove and insert your SD card so rasbpian can re-detect it.

 

 

 

 

 

 

Setting up NOOBS:

For this step you need to download this zipfile: https://gitlab.com/raspberryShake-public/raspShake-SD-img/raw/master/raspishake-release.zip?inline=false

When your SD card is re-detected, open it in the file manager from the pop-up window.
Here I have the SD card open in the right window, and the raspberry shake zip open in the left

Open Action -> Extract, and copy the path for the SD card into the field here:
This extract step might take a while, after its done you can eject the SD card and you have a finished raspberry shake install image!

 

The next steps are actually setting up and connecting to the raspberry-shake, the indepth manual and tutorials for this process can be found here: https://manual.raspberryshake.org