2021/08/28

Flirc Raspberry Pi 4 Case heat test

 I recently got a Flirc case for my Raspberry Pi4 and was unsure if it would help the temperature of the CPU under a heavy load. So after reading mixed impressions of similar cases with builtin heatsinks on the internet, I decided I needed to run my own tests.

TLDR; It's a good looking case that keeps the temperature low enough and Wifi still works well.

You can see in the chart that in the first test the Pi without a case is warmer at idle and hits the throttling above 83º but in the second test after installing the Pi in the case the idle temperature is lower and the peak is about 60º. And yes, it took about 7 minutes to install it in the case and reboot.


Clearly the case kept the Pi cooler which was great! The case has a solid metal top that acts as a heatsink with a black plastic cover on the top and bottom. I also wondered if the plastic cover on the top reduced the heat dissipation, so I ran the test again and found that it made no noticeable difference. So I'm keeping the plastic on top.

Here is the test setup using Graphite/Grafana on my Pi to chart the temperature.

1. add a cron script to write the Pi temp to Graphite every minute.

#!/bin/sh

# Track the PI core temp in graphite

# whisper files are in /var/lib/graphite/whisper/

CARBON_PORT=2003

CARBON_SERVER=localhost

CARBON_PREFIX=pi

DATE=`date +%s`

VALUE=`/opt/vc/bin/vcgencmd measure_temp | egrep -o '[0-9]*\.[0-9]*'`

echo "$CARBON_PREFIX.temp $VALUE $DATE" | nc -N ${CARBON_SERVER} ${CARBON_PORT}

exit $?

2. install the load tester that will warm up all 4 of the CPU cores

sudo apt install stress-ng

3. the 10 minute stress test command

sudo stress-ng --cpu 0 --cpu-method fft -t 600 --times --tz --perf

The results without a case had fewer CPU cycles due to the throttling.

stress-ng: info:  [26124] dispatching hogs: 4 cpu

stress-ng: info:  [26124] cache allocate: using defaults, can't determine cache details from sysfs

stress-ng: info:  [26124] successful run completed in 600.88s (10 mins, 0.88 secs)

stress-ng: info:  [26124] cpu:

stress-ng: info:  [26124]          3,351,213,272,324 CPU Cycles                      5.58 B/sec

stress-ng: info:  [26124]          5,257,128,421,496 Instructions                    8.75 B/sec (1.569 instr. per cycle)

stress-ng: info:  [26124]              2,355,284,116 Branch Misses                   3.92 M/sec ( 0.00%)

stress-ng: info:  [26124]          1,117,147,979,068 Bus Cycles                      1.86 B/sec

stress-ng: info:  [26124]          1,925,684,309,644 Cache References                3.20 B/sec

stress-ng: info:  [26124]             70,192,888,528 Cache Misses                    0.12 B/sec ( 3.65%)

stress-ng: info:  [26124]          1,925,714,318,612 Cache L1D Read                  3.20 B/sec

stress-ng: info:  [26124]             70,209,791,620 Cache L1D Read Miss             0.12 B/sec

stress-ng: info:  [26124]            601,769,965,280 Cache L1D Write                 1.00 B/sec

stress-ng: info:  [26124]             39,275,045,820 Cache L1D Write Miss           65.36 M/sec

stress-ng: info:  [26124]          1,623,493,004,028 Cache L1I Read                  2.70 B/sec

stress-ng: info:  [26124]                237,104,488 Cache L1I Read Miss             0.39 M/sec

stress-ng: info:  [26124]             11,372,158,076 Cache DTLB Read Miss           18.93 M/sec

stress-ng: info:  [26124]              6,457,277,064 Cache DTLB Write Miss          10.75 M/sec

stress-ng: info:  [26124]                  3,019,056 Cache ITLB Read Miss            5.02 K/sec

stress-ng: info:  [26124]            680,066,666,288 Cache BPU Read                  1.13 B/sec

stress-ng: info:  [26124]              2,355,275,308 Cache BPU Read Miss             3.92 M/sec

stress-ng: info:  [26124]              1,316,252,132 Cache NODE Read                 2.19 M/sec

stress-ng: info:  [26124]                629,580,520 Cache NODE Write                1.05 M/sec

stress-ng: info:  [26124]          2,311,855,064,928 CPU Clock                       3.85 B/sec

stress-ng: info:  [26124]          2,311,958,359,704 Task Clock                      3.85 B/sec

stress-ng: info:  [26124]                        156 Page Faults Total               0.26 /sec 

stress-ng: info:  [26124]                        156 Page Faults Minor               0.26 /sec 

stress-ng: info:  [26124]                          0 Page Faults Major               0.00 /sec 

stress-ng: info:  [26124]                    130,392 Context Switches              217.00 /sec 

stress-ng: info:  [26124]                        916 CPU Migrations                  1.52 /sec 

stress-ng: info:  [26124]                          0 Alignment Faults                0.00 /sec 

stress-ng: info:  [26124]                          0 Emulation Faults                0.00 /sec 

stress-ng: info:  [26124]                        376 System Call Enter               0.63 /sec 

stress-ng: info:  [26124]                        372 System Call Exit                0.62 /sec 

stress-ng: info:  [26124]                      1,288 Kmalloc                         2.14 /sec 

stress-ng: info:  [26124]                          0 Kmalloc Node                    0.00 /sec 

stress-ng: info:  [26124]                      4,920 Kfree                           8.19 /sec 

stress-ng: info:  [26124]                      7,924 Kmem Cache Alloc               13.19 /sec 

stress-ng: info:  [26124]                          0 Kmem Cache Alloc Node           0.00 /sec 

stress-ng: info:  [26124]                     21,684 Kmem Cache Free                36.09 /sec 

stress-ng: info:  [26124]                        496 MM Page Alloc                   0.83 /sec 

stress-ng: info:  [26124]                      2,496 MM Page Free                    4.15 /sec 

stress-ng: info:  [26124]                  1,481,552 RCU Utilization                 2.47 K/sec

stress-ng: info:  [26124]                        732 Sched Migrate Task              1.22 /sec 

stress-ng: info:  [26124]                          0 Sched Move NUMA                 0.00 /sec 

stress-ng: info:  [26124]                    127,900 Sched Wakeup                  212.86 /sec 

stress-ng: info:  [26124]                          0 Sched Proc Exec                 0.00 /sec 

stress-ng: info:  [26124]                          0 Sched Proc Exit                 0.00 /sec 

stress-ng: info:  [26124]                          0 Sched Proc Fork                 0.00 /sec 

stress-ng: info:  [26124]                        136 Sched Proc Free                 0.23 /sec 

stress-ng: info:  [26124]                          0 Sched Proc Hang                 0.00 /sec 

stress-ng: info:  [26124]                          0 Sched Proc Wait                 0.00 /sec 

stress-ng: info:  [26124]                    130,392 Sched Switch                  217.00 /sec 

stress-ng: info:  [26124]                          4 Signal Generate                 0.01 /sec 

stress-ng: info:  [26124]                          4 Signal Deliver                  0.01 /sec 

stress-ng: info:  [26124]                    710,424 IRQ Entry                       1.18 K/sec

stress-ng: info:  [26124]                    710,424 IRQ Exit                        1.18 K/sec

stress-ng: info:  [26124]                     84,488 Soft IRQ Entry                140.61 /sec 

stress-ng: info:  [26124]                     84,488 Soft IRQ Exit                 140.61 /sec 

stress-ng: info:  [26124]                          0 Writeback Dirty Inode           0.00 /sec 

stress-ng: info:  [26124]                          0 Writeback Dirty Page            0.00 /sec 

stress-ng: info:  [26124]                          0 Migrate MM Pages                0.00 /sec 

stress-ng: info:  [26124]                      3,304 SKB Consume                     5.50 /sec 

stress-ng: info:  [26124]                      1,016 SKB Kfree                       1.69 /sec 

stress-ng: info:  [26124] cpu:

stress-ng: info:  [26124]          cpu-thermal   82.05 °C

stress-ng: info:  [26124] for a 600.88s run time:

stress-ng: info:  [26124]    2403.51s available CPU time

stress-ng: info:  [26124]    2310.76s user time   ( 96.14%)

stress-ng: info:  [26124]       4.64s system time (  0.19%)

stress-ng: info:  [26124]    2315.40s total time  ( 96.33%)

stress-ng: info:  [26124] load average: 4.24 3.60 2.36


The results with the case

stress-ng: info:  [2458] dispatching hogs: 4 cpu

stress-ng: info:  [2458] cache allocate: using defaults, can't determine cache details from sysfs

stress-ng: info:  [2458] successful run completed in 600.89s (10 mins, 0.89 secs)

stress-ng: info:  [2458] cpu:

stress-ng: info:  [2458]          3,466,468,096,172 CPU Cycles                      5.77 B/sec

stress-ng: info:  [2458]          5,433,442,835,240 Instructions                    9.04 B/sec (1.567 instr. per cycle)

stress-ng: info:  [2458]              2,428,481,032 Branch Misses                   4.04 M/sec ( 0.00%)

stress-ng: info:  [2458]          1,155,591,178,712 Bus Cycles                      1.92 B/sec

stress-ng: info:  [2458]          1,990,529,210,212 Cache References                3.31 B/sec

stress-ng: info:  [2458]             72,971,962,212 Cache Misses                    0.12 B/sec ( 3.67%)

stress-ng: info:  [2458]          1,990,582,334,864 Cache L1D Read                  3.31 B/sec

stress-ng: info:  [2458]             72,956,292,228 Cache L1D Read Miss             0.12 B/sec

stress-ng: info:  [2458]            621,927,779,860 Cache L1D Write                 1.04 B/sec

stress-ng: info:  [2458]             40,460,573,360 Cache L1D Write Miss           67.33 M/sec

stress-ng: info:  [2458]          1,667,242,631,912 Cache L1I Read                  2.77 B/sec

stress-ng: info:  [2458]                232,913,956 Cache L1I Read Miss             0.39 M/sec

stress-ng: info:  [2458]             11,851,802,864 Cache DTLB Read Miss           19.72 M/sec

stress-ng: info:  [2458]              6,597,373,720 Cache DTLB Write Miss          10.98 M/sec

stress-ng: info:  [2458]                  3,412,088 Cache ITLB Read Miss            5.68 K/sec

stress-ng: info:  [2458]            702,798,169,272 Cache BPU Read                  1.17 B/sec

stress-ng: info:  [2458]              2,428,041,468 Cache BPU Read Miss             4.04 M/sec

stress-ng: info:  [2458]                866,617,940 Cache NODE Read                 1.44 M/sec

stress-ng: info:  [2458]                331,821,000 Cache NODE Write                0.55 M/sec

stress-ng: info:  [2458]          2,321,089,381,860 CPU Clock                       3.86 B/sec

stress-ng: info:  [2458]          2,321,181,986,648 Task Clock                      3.86 B/sec

stress-ng: info:  [2458]                        156 Page Faults Total               0.26 /sec 

stress-ng: info:  [2458]                        156 Page Faults Minor               0.26 /sec 

stress-ng: info:  [2458]                          0 Page Faults Major               0.00 /sec 

stress-ng: info:  [2458]                    108,616 Context Switches              180.76 /sec 

stress-ng: info:  [2458]                        776 CPU Migrations                  1.29 /sec 

stress-ng: info:  [2458]                          0 Alignment Faults                0.00 /sec 

stress-ng: info:  [2458]                          0 Emulation Faults                0.00 /sec 

stress-ng: info:  [2458]                        376 System Call Enter               0.63 /sec 

stress-ng: info:  [2458]                        372 System Call Exit                0.62 /sec 

stress-ng: info:  [2458]                      1,476 Kmalloc                         2.46 /sec 

stress-ng: info:  [2458]                          0 Kmalloc Node                    0.00 /sec 

stress-ng: info:  [2458]                      7,296 Kfree                          12.14 /sec 

stress-ng: info:  [2458]                     13,092 Kmem Cache Alloc               21.79 /sec 

stress-ng: info:  [2458]                          0 Kmem Cache Alloc Node           0.00 /sec 

stress-ng: info:  [2458]                     27,704 Kmem Cache Free                46.10 /sec 

stress-ng: info:  [2458]                        648 MM Page Alloc                   1.08 /sec 

stress-ng: info:  [2458]                      4,620 MM Page Free                    7.69 /sec 

stress-ng: info:  [2458]                  1,485,888 RCU Utilization                 2.47 K/sec

stress-ng: info:  [2458]                      1,348 Sched Migrate Task              2.24 /sec 

stress-ng: info:  [2458]                          0 Sched Move NUMA                 0.00 /sec 

stress-ng: info:  [2458]                    107,156 Sched Wakeup                  178.33 /sec 

stress-ng: info:  [2458]                          0 Sched Proc Exec                 0.00 /sec 

stress-ng: info:  [2458]                          0 Sched Proc Exit                 0.00 /sec 

stress-ng: info:  [2458]                          0 Sched Proc Fork                 0.00 /sec 

stress-ng: info:  [2458]                        228 Sched Proc Free                 0.38 /sec 

stress-ng: info:  [2458]                          0 Sched Proc Hang                 0.00 /sec 

stress-ng: info:  [2458]                          0 Sched Proc Wait                 0.00 /sec 

stress-ng: info:  [2458]                    108,616 Sched Switch                  180.76 /sec 

stress-ng: info:  [2458]                          0 Signal Generate                 0.00 /sec 

stress-ng: info:  [2458]                          4 Signal Deliver                  0.01 /sec 

stress-ng: info:  [2458]                    702,072 IRQ Entry                       1.17 K/sec

stress-ng: info:  [2458]                    702,072 IRQ Exit                        1.17 K/sec

stress-ng: info:  [2458]                    115,840 Soft IRQ Entry                192.78 /sec 

stress-ng: info:  [2458]                    115,840 Soft IRQ Exit                 192.78 /sec 

stress-ng: info:  [2458]                          0 Writeback Dirty Inode           0.00 /sec 

stress-ng: info:  [2458]                          0 Writeback Dirty Page            0.00 /sec 

stress-ng: info:  [2458]                          0 Migrate MM Pages                0.00 /sec 

stress-ng: info:  [2458]                      3,436 SKB Consume                     5.72 /sec 

stress-ng: info:  [2458]                      1,148 SKB Kfree                       1.91 /sec 

stress-ng: info:  [2458] cpu:

stress-ng: info:  [2458]          cpu-thermal   59.77 °C

stress-ng: info:  [2458] for a 600.89s run time:

stress-ng: info:  [2458]    2403.56s available CPU time

stress-ng: info:  [2458]    2315.14s user time   ( 96.32%)

stress-ng: info:  [2458]       3.44s system time (  0.14%)

stress-ng: info:  [2458]    2318.58s total time  ( 96.46%)

stress-ng: info:  [2458] load average: 4.00 3.59 2.04


That's it.


2020/04/15

MagicHome RGB light strip with ESPHome

I’ve been play with ESPHome for a bit and it is turning out to be really great. I love that I can just write declarative YAML to define what my device should do and it just works. I had been learning about the esp-01 devices using the Arduino IDE and setting up my own OTA system, coding my own MQTT functions, and my own temperature sensor and alerting logic so I already understood what I was doing at that level. That was all very fun too but ESPHome made it so much easier that I’ll probably be hooked for a while.
ESPHome works on all kinds of devices based on the ESP8266 or ESP32 chips. I picked up a MagicHome RGB light strip controller device because it has that chip and I wanted the option to customize it. Mine actually has a ESP8285 chip, which is just a smaller/cheaper version of the ESP8266.
I have this old big metal “R” on the wall that I wanted to backlight and this turned out to be a perfect match for this project. The R was a birthday gift from my wife. She found it in an antique store and learned that it was originally part of a SEARS store sign.

Attaching the light strip

I constructed a spacer with foam core and duct tape to hold the R about 1 inch off the wall and give a place to stick the adhesive RGBW light strip. It was quick, easy to work, with and turned out pretty well being all hidden behind the R.

Soldering required to access the serial port

Soldering is not really that hard but it’s a skill that can take a little practice. Removing components from an old circuit board is a good way to learn the basics. I’ve been using this cordless soldering iron and it’s super convenient.
To flash the ESP chip you need access to the serial connectors. Once ESPHome is flashed to the chip you’ll never need it again so just go ahead and desolder the wires. These sites have good instructions on where the wires need to be soldered:
Be sure to notice the part about connecting GPIO-0 to Ground to put the chip into programming mode. I use this little USB ESP-01 programmer and it has a convenient switch to do that.
Now you are ready to flash new firmware.

Stock firmware backup/restore

This is optional but sometimes it’s nice to have the option to restore the device if needed.
cd ~/esphome/ && python3 -m venv venv
source venv/bin/activate
pip install tornado esptool esphome

# backup
venv/bin/esptool.py --port /dev/cu.usbserial-1420 read_flash 0x00000 0x100000 original_firmware.bin

# erase
venv/bin/esptool.py --port /dev/cu.usbserial-1420 erase_flash

# restore
venv/bin/esptool.py --port /dev/cu.usbserial-1420 write_flash -fs 1MB -fm dout 0x0 original_firmware.bin

First time flashing ESPHome

Install ESPHome (see the getting started guides)
cd ~/esphome/ && python3 -m venv venv
source venv/bin/activate
pip install tornado esptool esphome
Flash from the command line
esphome config/magichome_led_strip.yaml wizard
esphome config/magichome_led_strip.yaml run
Flash from the web interface at http://localhost:6052/:
esphome config/ dashboard
After ESPHome is flashed everything can now be re-flashed OTA or over-the-air. You can desolder the extra wires and put away your USB programmer.

The YAML file

To reconfigure the device with ESPHome you just change the YAML file and upload it.
When you want to make changes start up the web interface at http://localhost:6052/
esphome config/ dashboard
Edit your YAML file and upload it. This is what my YAML file looks like:
esphome:
  name: magichome_led_strip
  platform: ESP8266
  board: esp01_1m

wifi:
  ssid: "your-wifi-network-name"
  password: "your-wifi-network-password"

api:

logger:

ota:

# https://esphome.io/components/mqtt.html
mqtt:
  broker: "your-mqtt-server-ip-address"
  username: "your-mqtt-username"
  password: "your-mqtt-password"

light:
  - platform: rgb
    id: light_1
    name: "LED Strip"
    red: red_channel
    green: green_channel
    blue: blue_channel
    effects:
      - automation:
          name: Fade
          sequence:
            - light.control:
                id: light_1
                brightness: 100%
            - delay: 1s
            - light.control:
                id: light_1
                brightness: 50%
            - delay: 1s

output:
  - platform: esp8266_pwm
    id: red_channel
    pin: GPIO5
  - platform: esp8266_pwm
    id: green_channel
    pin: GPIO12
  - platform: esp8266_pwm
    id: blue_channel
    pin: GPIO13

# https://esphome.io/components/remote_receiver.html
remote_receiver:
  dump: all
  pin:
    number: GPIO4
    inverted: True

binary_sensor:
  - platform: remote_receiver
    name: "on"
    nec:
      address: 0x00FF
      command: 0xB04F
    on_press:
      then:
        - light.control:
            id: light_1
            state: on
        - light.turn_on: light_1

  - platform: remote_receiver
    name: "off"
    nec:
      address: 0x00FF
      command: 0xF807
    on_press:
      then:
        - light.control:
            id: light_1
            state: off
        - light.turn_off: light_1

  - platform: remote_receiver
    name: "red"
    nec:
      address: 0x00FF
      command: 0x9867
    on_press:
      then:
        - light.control:
            id: light_1
            red: 100%
            green: 0%
            blue: 0%

  - platform: remote_receiver
    name: "green"
    nec:
      address: 0x00FF
      command: 0xD827
    on_press:
      then:
        - light.control:
            id: light_1
            red: 0%
            green: 100%
            blue: 0%

  - platform: remote_receiver
    name: "blue"
    nec:
      address: 0x00FF
      command: 0x8877
    on_press:
      then:
        - light.control:
            id: light_1
            red: 0%
            green: 0%
            blue: 100%

  - platform: remote_receiver
    name: "white"
    nec:
      address: 0x00FF
      command: 0xA857
    on_press:
      then:
        - light.control:
            id: light_1
            red: 100%
            green: 100%
            blue: 100%

  - platform: remote_receiver
    name: "brighter"
    nec:
      address: 0x00FF
      command: 0x906F
    on_press:
      then:
        - light.control:
            id: light_1
            brightness: 100%

  - platform: remote_receiver
    name: "dimmer"
    nec:
      address: 0x00FF
      command: 0xB847
    on_press:
      then:
        - light.control:
            id: light_1
            brightness: 50%

  - platform: remote_receiver
    name: "fade"
    nec:
      address: 0x00FF
      command: 0x58A7
    on_press:
      then:
        - light.control:
            id: light_1
            effect: Fade

  - platform: remote_receiver
    name: "r2"
    nec:
      address: 0x00FF
      command: 0xE817
    on_press:
      then:
        - light.control:
            id: light_1
            red: 100%
            green: 30%
            blue: 0%
  - platform: remote_receiver
    name: "r3"
    nec:
      address: 0x00FF
      command: 0x02FD
    on_press:
      then:
        - light.control:
            id: light_1
            red: 100%
            green: 50%
            blue: 0%
  - platform: remote_receiver
    name: "r4"
    nec:
      address: 0x00FF
      command: 0x50AF
    on_press:
      then:
        - light.control:
            id: light_1
            red: 60%
            green: 40%
            blue: 0%
  - platform: remote_receiver
    name: "r5"
    nec:
      address: 0x00FF
      command: 0x38C7
    on_press:
      then:
        - light.control:
            id: light_1
            red: 100%
            green: 100%
            blue: 20%

  - platform: remote_receiver
    name: "g2"
    nec:
      address: 0x00FF
      command: 0x48B7
    on_press:
      then:
        - light.control:
            id: light_1
            red: 0%
            green: 100%
            blue: 50%
  - platform: remote_receiver
    name: "g3"
    nec:
      address: 0x00FF
      command: 0x32CD
    on_press:
      then:
        - light.control:
            id: light_1
            red: 30%
            green: 100%
            blue: 100%
  - platform: remote_receiver
    name: "g4"
    nec:
      address: 0x00FF
      command: 0x7887
    on_press:
      then:
        - light.control:
            id: light_1
            red: 0%
            green: 100%
            blue: 100%
  - platform: remote_receiver
    name: "g5"
    nec:
      address: 0x00FF
      command: 0x28D7
    on_press:
      then:
        - light.control:
            id: light_1
            red: 0%
            green: 50%
            blue: 50%

  - platform: remote_receiver
    name: "b2"
    nec:
      address: 0x00FF
      command: 0x6897
    on_press:
      then:
        - light.control:
            id: light_1
            red: 30%
            green: 0%
            blue: 100%
  - platform: remote_receiver
    name: "b3"
    nec:
      address: 0x00FF
      command: 0x20DF
    on_press:
      then:
        - light.control:
            id: light_1
            red: 70%
            green: 0%
            blue: 100%
  - platform: remote_receiver
    name: "b4"
    nec:
      address: 0x00FF
      command: 0x708F
    on_press:
      then:
        - light.control:
            id: light_1
            red: 100%
            green: 0%
            blue: 100%
  - platform: remote_receiver
    name: "b5"
    nec:
      address: 0x00FF
      command: 0xF00F
    on_press:
      then:
        - light.control:
            id: light_1
            red: 100%
            green: 0%
            blue: 50%

That’s all I’ve got! Have fun!