Thursday, January 23, 2025

Easy Graphing of Temperatures with RasPI and NodeRed

-----

After hearing over and over how quick and easy the graphical programming environment for Node-Red was we decided to give it a try with an old Raspberry PI Model B that was 'resting' in a drawer.   Conclusion:  It's easy; it's really really easy.   Plus, there is a large user base that has created examples and libraries for just about any application you can dream up.

-----
Node-Red is free and the install is easy and well documented on their website.  For our Node-Red experiment we decide to graph the ambient air temperature as measured by a DS18B20 and the CPU core temperature of the Raspberry PI Model B.   Connect the DS18B20 sensor like this:

-----

It didn't take us long at all to 'noodle' up this:

-----

Then we went into the "Layout" tab to format what the graphs would look like:

----

All in all the project, including the Node-Red install; was probably under two hours.  That's pretty damn quick for going from zero knowledge to serving up nice graphs.

-----

Importing or Exporting code is easy as well.  It's basically "copy/past".  Here is our code for the project:

[
    {
        "id": "018abb4b7bfb7e86",
        "type": "exec",
        "z": "c0bb5756099d6dbc",
        "command": "vcgencmd measure_temp",
        "addpay": false,
        "append": "",
        "useSpawn": "false",
        "timer": "",
        "oldrc": false,
        "name": "Get CPU Temp",
        "x": 420,
        "y": 40,
        "wires": [
            [
                "05c0f7272e5bc7e0"
            ],
            [],
            []
        ]
    },
    {
        "id": "05c0f7272e5bc7e0",
        "type": "function",
        "z": "c0bb5756099d6dbc",
        "name": "Parse Temp",
        "func": "var tempC = parseFloat(msg.payload.replace('temp=', '').replace(\"'C\", ''));\nvar tempF = (tempC * 9/5) + 32;\nmsg.payload = tempF.toFixed(2);\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 630,
        "y": 40,
        "wires": [
            [
                "7dfbce89f48de845",
                "d97496ad6fb77af6"
            ]
        ]
    },
    {
        "id": "7dfbce89f48de845",
        "type": "ui_chart",
        "z": "c0bb5756099d6dbc",
        "name": "",
        "group": "7",
        "order": 8,
        "width": 11,
        "height": 5,
        "label": "CPU (°F)",
        "chartType": "line",
        "legend": "false",
        "xformat": "HH:mm",
        "interpolate": "linear",
        "nodata": "",
        "dot": false,
        "ymin": "",
        "ymax": "",
        "removeOlder": "7",
        "removeOlderPoints": "10080",
        "removeOlderUnit": "86400",
        "cutout": 0,
        "useOneColor": false,
        "useUTC": false,
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838",
            "#000000",
            "#000000",
            "#000000",
            "#000000",
            "#000000",
            "#000000"
        ],
        "outputs": 1,
        "useDifferentColor": false,
        "className": "",
        "x": 880,
        "y": 40,
        "wires": [
            []
        ]
    },
    {
        "id": "d97496ad6fb77af6",
        "type": "ui_gauge",
        "z": "c0bb5756099d6dbc",
        "name": "",
        "group": "7",
        "order": 7,
        "width": 5,
        "height": 5,
        "gtype": "donut",
        "title": "CPU (°F)",
        "label": "°F",
        "format": "{{value}}",
        "min": "110",
        "max": "175",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "diff": false,
        "className": "",
        "x": 880,
        "y": 80,
        "wires": []
    },
    {
        "id": "3b8516632c6153ec",
        "type": "debug",
        "z": "c0bb5756099d6dbc",
        "name": "DC18B20 Temp",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 900,
        "y": 260,
        "wires": []
    },
    {
        "id": "e19a60a2f08ac386",
        "type": "inject",
        "z": "c0bb5756099d6dbc",
        "name": "Every 60 secs",
        "props": [],
        "repeat": "60",
        "crontab": "",
        "once": true,
        "onceDelay": "1",
        "topic": "",
        "x": 160,
        "y": 40,
        "wires": [
            [
                "018abb4b7bfb7e86"
            ]
        ]
    },
    {
        "id": "a3b79e7f7975fa73",
        "type": "ds18b20",
        "z": "c0bb5756099d6dbc",
        "name": "DS18B20",
        "sensorid": "28-089bd445e089",
        "timer": "1",
        "x": 380,
        "y": 220,
        "wires": [
            [
                "3d28949a3fa611d3"
            ]
        ]
    },
    {
        "id": "3d28949a3fa611d3",
        "type": "function",
        "z": "c0bb5756099d6dbc",
        "name": "C_to_F",
        "func": "var tempc = msg.payload;\nvar tempf = tempc * 9/5 + 32;\ntempf = tempf.toFixed(2);\nmsg.payload = tempf;\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 600,
        "y": 220,
        "wires": [
            [
                "3b8516632c6153ec",
                "61cf75a9eeeb79be",
                "e146810a6d814e42"
            ]
        ]
    },
    {
        "id": "e146810a6d814e42",
        "type": "ui_chart",
        "z": "c0bb5756099d6dbc",
        "name": "",
        "group": "7",
        "order": 3,
        "width": 11,
        "height": 9,
        "label": "°F",
        "chartType": "line",
        "legend": "false",
        "xformat": "HH:mm",
        "interpolate": "linear",
        "nodata": "",
        "dot": false,
        "ymin": "",
        "ymax": "",
        "removeOlder": "7",
        "removeOlderPoints": "10080",
        "removeOlderUnit": "86400",
        "cutout": 0,
        "useOneColor": false,
        "useUTC": false,
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838",
            "#000000",
            "#000000",
            "#000000",
            "#000000",
            "#000000",
            "#000000"
        ],
        "outputs": 1,
        "useDifferentColor": false,
        "className": "",
        "x": 870,
        "y": 180,
        "wires": [
            []
        ]
    },
    {
        "id": "61cf75a9eeeb79be",
        "type": "ui_gauge",
        "z": "c0bb5756099d6dbc",
        "name": "",
        "group": "7",
        "order": 2,
        "width": 5,
        "height": 9,
        "gtype": "donut",
        "title": "Ambient (°F)",
        "label": "°F",
        "format": "{{value}}",
        "min": "80",
        "max": "110",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "diff": false,
        "className": "",
        "x": 890,
        "y": 220,
        "wires": []
    },
    {
        "id": "cc4248afd8356380",
        "type": "debug",
        "z": "c0bb5756099d6dbc",
        "name": "debug 1",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 880,
        "y": 400,
        "wires": []
    },
    {
        "id": "1553124d816901d2",
        "type": "inject",
        "z": "c0bb5756099d6dbc",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "1",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 170,
        "y": 360,
        "wires": [
            [
                "cc4248afd8356380",
                "6f3d2d25b6ad464e"
            ]
        ]
    },
    {
        "id": "6f3d2d25b6ad464e",
        "type": "ui_digital_clock",
        "z": "c0bb5756099d6dbc",
        "name": "",
        "group": "7",
        "order": 5,
        "width": 4,
        "height": 1,
        "x": 890,
        "y": 360,
        "wires": []
    },
    {
        "id": "7",
        "type": "ui_group",
        "name": "RasPI-3B",
        "tab": "6",
        "order": 1,
        "disp": true,
        "width": 16,
        "collapse": false,
        "className": ""
    },
    {
        "id": "6",
        "type": "ui_tab",
        "name": "Home",
        "icon": "dashboard",
        "order": 1
    }
]

-----