Showing posts with label Raspberry Pi B. Show all posts
Showing posts with label Raspberry Pi B. Show all posts

Monday, 26 December 2022

Small DC/DC UPS


5V to 5V DC UPS

Backup time is approximately 1 hour using 3000mAh 18650 battery. Or, you can get a proper UPS Hat like this one:

UPS Hat with Raspberry Pi (bottom)





It is very tempting to make a UPS from generic lithium battery chargers, especially if you just want to power devices like your internet modems and WiFi. And some power banks can be recharged as well as output power at the same time. A few can have their input power turned on and off without dropping their output, just like a UPS. But there are problems: often the power bank heats up. 

It seems lithium batteries may not like to be float-charged. A common lithium charger IC like the TP4056 measures the current supplied to the battery and turns off charging when it thinks the battery is full. Diverting part of this current to supply the load at the same time interferes with this and may even cause the charger to fail to stop charging the battery. The latter may heat up. In particular lithium polymer batteries may swell up burst or pop its enclosure. Dr. Gough's has an excellent writeup on the subject.

Lithium Polymer Battery

It is safer to use the bulkier lithium ion protected 18650 format, with safety vents, and extra overcurrent and overtemperature circuits. They are often slightly larger the the unprotected ones.

Typical Protected 18650 battery

Another thing to look for is the metallic strip or tab running from one end to the other.

Note the conductive strip running vertically down the 18650 protected battery on the right

 

18650 batteries are also easy to replace if mounted in holders. They are also surprisingly economical.

18650 are not AA size batteries


The despite its name the Geekworm UPS Hat for Raspberry Pi is NOT a UPS. My battery swelled up within days running as one. It works perfectly well if the Hat was charged with Pi turned off. Note a Pi when shutdown via software still draws 100mA.

The late unlamented Geekworm UPS Hat V1.0

CAUTION

It is generally NOT ADVISABLE to repurpose generic lithium chargers as UPS, Especially using no-name TP4056-based chargers like this one! Lithium battery-based UPS need to be designed for that purpose. When charging your batteries, you generally do not turn on the load. When the load is connected, the charger is not. Do not leave this setup unattended - there is risk of fire. I am also assuming you are familiar with electronics and its attendant hazards. The purpose of this project is to exercise your electronics chops i.e., to get some insight into lithium battery UPS design issues. This is NOT a viable design. 

Having settled on the 18650, I happened to have this no name 'TP4056 Lithium Battery Charger with Protection' board in my parts bin. The PCB was marked '03962A' and there is even a schematic.

The deliciously cheap 'TP4056 Lithium Battery Charger with Protection' 

 
Schematic for 'TP4056 Lithium Battery Charger with Protection' 

 A straightforward connection as a UPS might look something like this. 

Wiring diagram from Electrothinks

The UPS battery will switch over and back very quickly if the charger drops out or in. The problem is the red charging indicator will not go off as long as the load is also present. And this will result in the 18650 with a somewhat shorter service life.

Now if I add 2 schottky diodes thus, the TP4056 Charger will turn off charging with load connected:


The problem is when running from battery the output is just 4V maximum, too low for the Raspberry Pi. Luckily I have on hand a cheap and cheerful MT3608 DC-DC Boost Converter:

MT3608 DC-DC Boost


 The resulting schematic is:


Battery output boosted to 5V using an MT3608

Note you have to adjust the the MT3608 output before you connect the load. While these generic boards generally work, the quality of the assembly can be a little variable, with dry joints or bent pins. A bent pin in the variable resistor can result in an output of over 20V!

There are quite a few inadequacies: the input 5V to the charger needs to be steady, between 7V-4.6V. Too high and the TP4056 will be damaged. Too low and it will fail to forward-bias the schottky diode and cause the load to be supplied from the battery which means the charger will not switch off and the battery may overheat with continous use. 

This is a little problematic as a UPS is supposed to tolerate a wide variation in input voltages. In my case my 5V is supplied from a mains 5V 2A adapter which works for me. You need to re-test when you change to different input 5V sources or loads. In my case a Raspberry Pi Model B draws different loads depending on use of dongles; even plugging in the Ethernet connector will increase draw.

Happy Trails. 


Tuesday, 7 December 2021

Did I leave the Air Conditioner On? Indicator LED detection using Raspberry Pi and OpenCV

 

Air Conditioner Indoor Unit with Yellow Indicator LED

Air conditioners are essential in hot and humid Malaysia, especially if you want to work from home. Most of us have occasionally wondered if we have left it on after we left the house: the resulting electricity bill can be a nasty surprise. Most times you cannot do much about it, save for going back home to check.

But then, I managed to hack its infrared remote using an ESP8266, which made it an Internet of Things (IoT) device, which lets me turn it on and off from my smartphone. Now I have a need to know if I left the aircond turned on at home.  

When the indoor unit comes on, there is a beep and an orange LED lights up. The standard way is to mount an optocoupler diode in series with the orange LED, wire the optocoupler output to an ESP8266 and the resulting IoT will reliably report the aircond on/off status every time.

But variety, they say, is the spice of life, and I happened to have an obsolete Raspberry Pi Model B with OpenCV installed. And lots of ancient 640x480 webcams. Granted the lighting conditions would change through the day, but surely it can recognize that round orange light with some consistency?

USB webcam looking at the indicator LED from 3 feet away

It would be a bonus if software can be added later to detect that beep. That would have other applications like detection of smoke alarms' beeps, thunder, doorbell chimes and other interesting sounds. But that is another blog post.

OpenCV Raspberry Pi Model B with LAN connection (ie 'headless' mode)

 Isaac Vidas looks like a good starting point, first using an HSV transform to isolate the color of interest, then using cv2.HoughCircles() to precisely locate the LED itself. 

Image after HSV transform

I did need some additional help in setting the color thresholds required in his code to:

# Get lower orange hue
lower_orange_hue = create_hue_mask(hsv_image, [0, 0, 255], [0, 255, 255]) 
# Get higher orange hue 
higher_orange_hue = create_hue_mask(hsv_image, [0, 0, 255], [38, 255, 255])

There is a handy python script by nathancy here, and together with a HSV color wheel, my threshold values could be determined using several images of the aircond LED under different lighting conditions.

HSV Color wheel

  


Image after color filtering



Firstof, you will be needing a programs to view the USB webcam video and still frames. I use mplayer and feh:

# apt-get install mplayer
# apt-get install feh

You set the Pi via raspi-config not to run the X Server (ie the GUI desktop), but it helps to have the X libraries installed. From your laptop/desktop you just ssh in:
fred@pi:~ $ ssh -t -Y 12.34.56.78

And from there, mplayer should display the video on your desktop. This lets you position the camera properly.
fred@pi:~ $ mplayer tv://

To get 10 still frames after 10s (some cameras auto-adjust brightness):
fred@pi:~ $ mplayer -vo jpeg -frames 10 -ss 10 -brightness 25 tv://

You can use 'mplayer -loop 0' to display the still images, but they flash on and off rather annoyingly. I much prefer something like feh:
fred@pi:~ $ feh .images/image_on.png

And best of all, the openCV code will execute as if you were using the Pi's console (ie HDMI).

Having selected your camera position, you should probably make a set of images under different lighting conditions. I used a fragment of Isaac Vidas's code to do this, in particular to see the effect of lighting on the separate operations like blurring and HSV transformation. This is named webcamTest.py and is available on my github repository. You typically do:
 
fred@pi:~/checkLed $ source ~/opencv/OpenCV-4.0-py3/bin/activate
(OpenCV-4.0-py3) fred@pi:~/checkLed $

(OpenCV-4.0-py3) fred@pi:~/checkLed $ python ./webcamTest.py image_on.png 

Next, use the nathancy code, which I named hsvThresholder.py. 
(OpenCV-4.0-py3) fred@pi:~/checkLed $ python hsvThresholder.py

hsvThresholder.py: adjust the sliders at the bottom. Runs very slowly on a Pi B, so be patient and watch the console output in the window below

You want to adjust the various sliders in order to mask out all other regions of different color to your LED. A Raspberry Pi 1 Model B will be extremely slow here so patience is required. One way is to watch the bash console messages as they are much quicker to update than the picture. Copy the final settings from the console, which will be something like:
(hMin = 0 , sMin = 0, vMin = 85), (hMax = 28 , sMax = 255, vMax = 255)

My version of Isaac Vidas's code is named checkAC_led.py. and pretty much works as advertised, except it required a much larger (something like 6x diameter) image of the LED. I would have needed to mount my camera much closer, just 17cm from the LED. The other problem is the camera needs to be square over the LED as cv2.HoughCircles() do not detect ellipses very well. And line (ie hollow) circles worked better than a solid one.

Image with test circle added: this is the minimum size circle cv2.HoughCircles() will detect

Mounting my camera closer and square-on the LED is the correct solution. This also minimizes false alarms and improves reliability of detection. This probably means some sort of mounting bracket on the wall, and might get in the way when the air conditioner is being serviced. A software solution would be great, and the future beep detector would help filter out those false alarms ...

This led me to cv2.SimpleBlobDetection() code, which does much better with smaller and deformed circles. Take care to set minArea as large as possible: I actually counted the number of LED pixels in my HSV transform.

The gotcha here is that the HSV image has to be inverted for blob detection to work:
    h, s, image_gray = cv2.split(full_image)
    image_gray_neg = cv2.bitwise_not(image_gray) 
    detector = cv2.SimpleBlobDetector_create(params)
After conversion to grayscale and inversion

After successful blob detection


The final version, checkACvideo_led.py reads from the webcam instead of still image files, filters out false alarms based on the blob x and y coordinates and prints the air conditioner status. In its IoT form the print statement just needs to be modified to publish to an MQTT server like mosquitto.

So did I leave the air conditioner on? Hey Mycroft, is my air conditioner on or off?

Happy Trails





Monday, 6 December 2021

The Littlest Computer that Could: OpenCV using Raspberry Pi 1 Model B Rev 2

 

First there was the 1B: Raspberry Pi One Model B.

Now out of production, the Raspberry Pi One Model B was released in 2012, earlier than the Model A. I had a few lying unused in my parts box, some damaged by defective power supplies, but mostly superseded by better versions like the Pi 2, 3 and 4s. The Pi 1 Model B was the slowest, had only 512MB DRAM and used the sdcard as mass storage. The USB functionality was questionable: the LAN chip was internally routed through the USB bus which crippled its throughput. And since the Pi was always touchy about its 5V input power adding basic functionality like keyboard, hdmi USB was always a hit and miss affair.

Left: sdcard, right: micro-sdcard


The sdcard is getting very hard to find. You find micro-sdcard with an adapter but these tend to develop contact problems and corrupt the onboard filesystem. To make matters worse, a Pi Model B which cannot boot will have no indication: there is just that red power LED on and nothing else, and it looks pretty much like a dead Pi. Some 60% of my discarded Pi 1s simply had microsd adapter contact problems and could not boot.

On the plus side, the Pi 1 drew the least power amongst the Pi series which meant most old Android phone chargers could power it. It also had audio and video jacks, which were very handy with retro electronics. 

I managed put one to use monitoring my solar panel, but most of the little jobs are better served by the ESP8266 or the Microchip PIC. If only the Raspberry Pi Model B could run OpenCV; with a bit of nifty image processing, it might find a use, perhaps to check if my front gate has been left open, or the air conditioner left running, or if the smoke alarm is beeping. 

Most of the time, the Pi 3 is the minimum recommended model, but there is no mention Raspberry Pi One cannot be used. No harm trying; and since the install process can be left alone, it is easily done on the side. 



Raspberry Pi 1 Model B Rev 2 with infamous microsd adapter

$dd if=2021-10-30-raspios-bullseye-armhf-lite.img of=/dev/sdc

After the standard install of Raspbian, I use raspi-config to turn on the ssh server and set a fixed ethernetIP. It can then be used as a headless (ie no monitor or keyboard) system via ssh from a host laptop or desktop. After which there is the usual obligatory

# apt-get update --allow-releaseinfo-change
# apt-get upgrade

And the Pi model:

root@pi:~# cat /sys/firmware/devicetree/base/model
Raspberry Pi Model B Rev 2

Jeremy Morgan's OpenCV install worked for my Pi 3 before, but now instead it stops:

# pip install opencv-contrib-python
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting opencv-contrib-python
Downloading opencv-contrib-python-4.5.4.60.tar.gz (150.7 MB)
|��������������������������������| 150.4 MB 93 kB/s eta 0:00:04Killed

From 'dmesg -T' it looks like I ran out of memory:

[Tue Nov 23 18:03:30 2021] [ 5714]     0  5714    87141    21594     104       0

    21597             0 pip

[Tue Nov 23 18:03:30 2021] Out of memory: Kill process 5714 (pip) score 349 or sacrifice child

[Tue Nov 23 18:03:30 2021] Killed process 5714 (pip) total-vm:348564kB, anon-rss

:86376kB, file-rss:0kB, shmem-rss:0kB

[Tue Nov 23 18:03:30 2021] oom_reaper: reaped process 5714 (pip), now anon-rss:0

kB, file-rss:0kB, shmem-rss:0kB

My free memory is:
# free -m
              total        used        free      shared  buff/cache   available
Mem:            369          18         285           0          65         304
Swap:         15358          21       15337

And I can get a litte more by editing the boot partition's config.txt:
# vi /boot/config.txt

Add:
gpu_mem=16

And comment out
#start_x=1

After a reboot I get more memory:
# free -m
              total        used        free      shared  buff/cache   available
Mem:            477          31         338           6         106         390
Swap:            99           0          99
 
But this is still not enough. Now I could increase the swap file in my micro sdcard, but the thrashing might wear it out as the number of write operations is limited. Instead I used one of the many ancient thumbdrives, discarded just because of their low capacities. I ended up using a compactflash card for its speed:

# dd if=/dev/zero of=/dev/sda bs=1M count=1024
# mkswap /dev/sda
# swapon /dev/sda

# pip install --upgrade pip setuptools wheel
# python -m pip install --upgrade pip
# pip3 install opencv-contrib-python

pip seems to have gone walkabout so,

#  ln -s /usr/local/bin/pip /usr/bin/pip

Failure:
# pip install opencv-contrib-python
    File "setup.py", line 381, in _classify_installed_files_override
      with open(os.path.join(cmake_install_dir, "python", "cv2", "__init__.py"),
 'r') as opencv_init:
  FileNotFoundError: [Errno 2] No such file or directory: '_skbuild/linux-armv6l
-3.7/cmake-install/python/cv2/__init__.py'
  ----------------------------------------
  ERROR: Failed building wheel for opencv-contrib-python
Failed to build opencv-contrib-python
ERROR: Could not build wheels for opencv-contrib-python, which is required to in
stall pyproject.toml-based projects

Vishwesh Shrimali's instructions seem promising, and his minimum requirement is for a Pi 2. There are more separate bash commands which increases the chances for a successful debug. Since a fail is near certain, I chose to key in the commands manually instead of running Shrimali's script.

root@pi:/root/opencv# apt-get -y purge wolfram-engine
root@pi:/root/opencv# apt-get -y purge libreoffice*
root@pi:/root/opencv# apt-get -y clean
root@pi:/root/opencv# apt-get -y autoremove
root@pi:/root/opencv# apt -y update
root@pi:/root/opencv# apt -y upgrade
root@pi:/root/opencv# apt-get -y remove x264 libx264-dev
root@pi:/root/opencv# apt-get -y install build-essential checkinstall
 cmake pkg-config yasm
root@pi:/root/opencv# apt-get -y install git gfortran
root@pi:/root/opencv# apt-get -y install libjpeg8-dev libjasper-dev libpng12-dev
root@pi:/root/opencv# apt-get -y install libtiff5-dev
root@pi:/root/opencv# apt-get -y install libtiff-dev
root@pi:/root/opencv# apt-get -y install libxine2-dev libv4l-dev
root@pi:/root/opencv# cd /usr/include/linux
root@pi:/usr/include/linux# ln -s -f ../libv4l1-videodev.h videodev.h
root@pi:/usr/include/linux# cd $cwd
root@pi:/root/opencv#
root@pi:/root/opencv# apt-get -y install libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev
root@pi:/root/opencv# apt-get -y install libgtk2.0-dev libtbb-dev qt5-default                         
root@pi:/root/opencv# apt-get -y install libatlas-base-dev
root@pi:/root/opencv# apt-get -y install libmp3lame-dev libtheora-dev
root@pi:/root/opencv# apt-get -y install libvorbis-dev libxvidcore-dev libx264-dev
root@pi:/root/opencv# apt-get -y install libopencore-amrnb-dev libopencore-amrwb-dev 
root@pi:/root/opencv# apt-get -y install libavresample-dev
root@pi:/root/opencv# apt-get -y install x264 v4l-utils

            The following are optional:
root@pi:/root/opencv# apt-get -y install libprotobuf-dev protobuf-compiler
root@pi:/root/opencv# apt-get -y install libgoogle-glog-dev libgflags-dev 
root@pi:/root/opencv# apt-get -y install libgphoto2-dev libeigen3-dev libhdf5-dev doxygen

            Required python libraries
root@pi:/root/opencv# apt-get -y install python3-dev python3-pip

            Virtual environment:
fred@pi:~/opencv $ python3 -m venv OpenCV-4.0-py3
fred@pi:~/opencv $ echo "# Virtual Environment Wrapper" >> ~/.bashrc
fred@pi:~/opencv $ echo "alias workoncv-4.0=\"source /root/opencv/OpenCV-4.0-py3/bin/activate\"" >> ~/.bashrc                                       
fred@pi:~/opencv $ source /root/opencv/OpenCV-4.0-py3/bin/activate(OpenCV-4.0-py3) fred@pi:~/opencv $

 Increase the swap file from 100 to 1024:
(OpenCV-4.0-py3) fred@pi:~/opencv $ sudo sed -i 's/CONF_SWAPSIZE=100/CONF_SWAPSIZE=1024/g' /etc/dphys-swapfile
(OpenCV-4.0-py3) fred@pi:~/opencv $ sudo /etc/init.d/dphys-swapfile stop
[ ok ] Stopping dphys-swapfile (via systemctl): dphys-swapfile.service.      
(OpenCV-4.0-py3) fred@pi:~/opencv $ sudo /etc/init.d/dphys-swapfile start
[ ok ] Starting dphys-swapfile (via systemctl): dphys-swapfile.service.         

(OpenCV-4.0-py3) fred@pi:~/opencv $ pip install numpy dlib
(OpenCV-4.0-py3) fred@pi:~/opencv $ deactivate

This is an over 400MB porker of a file:
fred@pi:~/opencv $ git clone https://github.com/opencv/opencv.git

In retrospect I should have checked out 4.0.1 as having cv2.drawKeypoints() would have been handy.
fred@pi:~/opencv/opencv $ git checkout 4.0.0

fred@pi:~/opencv $ git clone https://github.com/opencv/opencv_contrib.git
fred@pi:~/opencv $ cd opencv_contrib
fred@pi:~/opencv/opencv_contrib $ git checkout 4.0.0

Then comes the config:
fred@pi:~/opencv/opencv/build $ cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE
_INSTALL_PREFIX=/home/heong/opencv/installation/OpenCV-4.0 -D INSTALL_C_EXAMPLES
=ON -D INSTALL_PYTHON_EXAMPLES=ON -D WITH_TBB=ON -D WITH_V4L=ON -D OPENCV_PYTHON3_INSTALL_PATH=/home/heong/opencv/OpenCV-4.0-py3/lib/python3.5/site-packages -D WITH_QT=ON -D WITH_OPENGL=ON  -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules -D BUILD_EXAMPLES=ON ..

Now for the make:
fred@pi:~/opencv/opencv/build $ CMAKE_INSTALL_PREFIX=/usr/local
fred@pi:~/opencv/opencv/build $ export CMAKE_INSTALL_PREFIX
fred@pi:~/opencv/opencv/build $ make

Produces the error
In file included from /home/fred/opencv/opencv_contrib/modules/cvv/src/qtutil/f
ilter/sobelfilterwidget.cpp:3:
/home/heong/opencv/opencv/modules/imgproc/include/opencv2/imgproc.hpp:208:5: not
e:   �FILTER_SCHARR�
     FILTER_SCHARR = -1
     ^~~~~~~~~~~~~
make[2]: *** [modules/cvv/CMakeFiles/opencv_cvv.dir/build.make:453: modules/cvv/
CMakeFiles/opencv_cvv.dir/src/qtutil/filter/sobelfilterwidget.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:12676: modules/cvv/CMakeFiles/opencv_cvv.dir/
all] Error 2
make: *** [Makefile:163: all] Error 2

From Nobuo Tsukamoto, in the file /home/fred/opencv/opencv_contrib/modules/cvv/src/qtutil/f
ilter/sobelfilterwidget.cpp added 'using namespace cv;' at line 13 thus:

#include "../../util/util.hpp"
#include "../filterfunctionwidget.hpp"
#include "../filterselectorwidget.hpp"

using namespace cv; // cmheong 2021-11-29

namespace cvv
{
namespace qtutil
{

SobelFilterWidget::SobelFilterWidget(QWidget *parent)

After which
fred@pi:~/opencv/opencv/build $ make
Produces the error
Scanning dependencies of target example_cpp_detect_mser
[ 89%] Building CXX object samples/cpp/CMakeFiles/example_cpp_detect_mser.dir/detect_mser.cpp.o
/home/fred/opencv/opencv/samples/cpp/detect_mser.cpp:28:10: fatal error: GL/glu.h: No such file or directory
 #include <GL/glu.h>
          ^~~~~~~~~~
compilation terminated.
make[2]: *** [samples/cpp/CMakeFiles/example_cpp_detect_mser.dir/build.make:63:
samples/cpp/CMakeFiles/example_cpp_detect_mser.dir/detect_mser.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:29519: samples/cpp/CMakeFiles/example_cpp_det
ect_mser.dir/all] Error 2
make: *** [Makefile:163: all] Error 2

From RajkiranVeldur, just do
root@pi:~#  apt-get install libglfw3-dev libgl1-mesa-dev libglu1-mesa-dev

After which
fred@pi:~/opencv/opencv/build $ make
Produces the link error
[ 89%] Linking CXX executable ../../bin/example_cpp_detect_mser
/usr/bin/ld: CMakeFiles/example_cpp_detect_mser.dir/detect_mser.cpp.o: in functi
on `draw(void*)':
detect_mser.cpp:(.text.startup.main+0x1c70): undefined reference to `gluPerspect
ive'
collect2: error: ld returned 1 exit status
make[2]: *** [samples/cpp/CMakeFiles/example_cpp_detect_mser.dir/build.make:134:
 bin/example_cpp_detect_mser] Error 1
make[1]: *** [CMakeFiles/Makefile2:29519: samples/cpp/CMakeFiles/example_cpp_det
ect_mser.dir/all] Error 2
make: *** [Makefile:163: all] Error 2

regpa mentioned that I need openGLU.so, but a brute-force search could not come up with one:
fred@pi:~/opencv/opencv/build $ sudo ls -lR / | grep -e openGLU 
fred@pi:~/opencv/opencv/build $

There is however, a file called libGLU.so mentioned by myinternetofthings:
fred@pi:~/opencv/opencv/build $ sudo ls -lR / 2>/dev/null | grep -e GLU.so
lrwxrwxrwx  1 root root       15 Sep 20  2015 libGLU.so -> libGLU.so.1.3.1
lrwxrwxrwx  1 root root       15 Sep 20  2015 libGLU.so.1 -> libGLU.so.1.3.1
-rw-r--r--  1 root root   358228 Sep 20  2015 libGLU.so.1.3.1

Added it to 2 separate files link.txt:

fred@pi:~/opencv/opencv/build $ cat samples/opengl/CMakeFiles/example_open
gl_opengl.dir/link.txt
/usr/bin/c++     -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-
dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wm
issing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -W
uninitialized -Winit-self -Wno-narrowing -Wno-delete-non-virtual-dtor -Wno-comme
nt -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -pthr
ead -fomit-frame-pointer -ffunction-sections -fdata-sections  -mfp16-format=ieee
 -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG  -DNDEBUG    -Wl,-
-gc-sections   CMakeFiles/example_opengl_opengl.dir/opengl.cpp.o  -o ../../bin/e
xample_opengl_opengl  -Wl,-rpath,/home/heong/opencv/opencv/build/lib -ldl -lm -l
pthread -lrt /usr/lib/arm-linux-gnueabihf/libGL.so ../../lib/libopencv_highgui.s
o.4.0.0 ../../lib/libopencv_videoio.so.4.0.0 ../../lib/libopencv_imgcodecs.so.4.
0.0 ../../lib/libopencv_imgproc.so.4.0.0 ../../lib/libopencv_core.so.4.0.0 /usr/
lib/arm-linux-gnueabihf/libGLU.so

fred@pi:~/opencv/opencv/build $ cat samples/cpp/CMakeFiles/example_cpp_det
ect_mser.dir/link.txt
/usr/bin/c++     -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-
dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wm
issing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -W
uninitialized -Winit-self -Wno-narrowing -Wno-delete-non-virtual-dtor -Wno-comme
nt -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -pthr
ead -fomit-frame-pointer -ffunction-sections -fdata-sections  -mfp16-format=ieee
 -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG  -DNDEBUG    -Wl,-
-gc-sections   CMakeFiles/example_cpp_detect_mser.dir/detect_mser.cpp.o  -o ../.
./bin/example_cpp_detect_mser  -Wl,-rpath,/home/heong/opencv/opencv/build/lib -l
dl -lm -lpthread -lrt /usr/lib/arm-linux-gnueabihf/libGL.so ../../lib/libopencv_
gapi.so.4.0.0 ../../lib/libopencv_stitching.so.4.0.0 ../../lib/libopencv_aruco.s
o.4.0.0 ../../lib/libopencv_bgsegm.so.4.0.0 ../../lib/libopencv_bioinspired.so.4
.0.0 ../../lib/libopencv_ccalib.so.4.0.0 ../../lib/libopencv_cvv.so.4.0.0 ../../
lib/libopencv_dnn_objdetect.so.4.0.0 ../../lib/libopencv_dpm.so.4.0.0 ../../lib/
libopencv_face.so.4.0.0 ../../lib/libopencv_freetype.so.4.0.0 ../../lib/libopenc
v_fuzzy.so.4.0.0 ../../lib/libopencv_hdf.so.4.0.0 ../../lib/libopencv_hfs.so.4.0
.0 ../../lib/libopencv_img_hash.so.4.0.0 ../../lib/libopencv_line_descriptor.so.
4.0.0 ../../lib/libopencv_reg.so.4.0.0 ../../lib/libopencv_rgbd.so.4.0.0 ../../l
ib/libopencv_saliency.so.4.0.0 ../../lib/libopencv_sfm.so.4.0.0 ../../lib/libope
ncv_stereo.so.4.0.0 ../../lib/libopencv_structured_light.so.4.0.0 ../../lib/libo
pencv_superres.so.4.0.0 ../../lib/libopencv_surface_matching.so.4.0.0 ../../lib/
libopencv_tracking.so.4.0.0 ../../lib/libopencv_videostab.so.4.0.0 ../../lib/lib
opencv_xfeatures2d.so.4.0.0 ../../lib/libopencv_xobjdetect.so.4.0.0 ../../lib/li
bopencv_xphoto.so.4.0.0 ../../lib/libopencv_shape.so.4.0.0 ../../lib/libopencv_p
hase_unwrapping.so.4.0.0 ../../lib/libopencv_optflow.so.4.0.0 ../../lib/libopenc
v_ximgproc.so.4.0.0 ../../lib/libopencv_datasets.so.4.0.0 ../../lib/libopencv_pl
ot.so.4.0.0 ../../lib/libopencv_text.so.4.0.0 ../../lib/libopencv_ml.so.4.0.0 ..
/../lib/libopencv_dnn.so.4.0.0 ../../lib/libopencv_video.so.4.0.0 ../../lib/libo
pencv_photo.so.4.0.0 ../../lib/libopencv_objdetect.so.4.0.0 ../../lib/libopencv_
calib3d.so.4.0.0 ../../lib/libopencv_features2d.so.4.0.0 ../../lib/libopencv_fla
nn.so.4.0.0 ../../lib/libopencv_highgui.so.4.0.0 ../../lib/libopencv_videoio.so.
4.0.0 ../../lib/libopencv_imgcodecs.so.4.0.0 ../../lib/libopencv_imgproc.so.4.0.
0 ../../lib/libopencv_core.so.4.0.0 /usr/lib/arm-linux-gnueabihf/libGLU.so

After which
fred@pi:~/opencv/opencv/build $ make

Completes successfully. But there is still the installation. Set the environment variable CMAKE_INSTALL_PREFIX so that:

fred@pi:~/opencv/opencv/build $ echo $CMAKE_INSTALL_PREFIX
/usr/local
fred@pi:~/opencv/opencv/build $ sudo make install

And a quick test run:
fred@pi:~/opencv/opencv/build $ source /home/fred/opencv/OpenCV-4.0-py3/bin/activate

(OpenCV-4.0-py3) fred@pi:~/opencv/opencv/build $ python
Python 3.7.3 (default, Jan 22 2021, 20:04:44)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> print(cv2.__version__)
4.0.0
>>> quit()

And there you have it, Raspberry Pi 1 Model B Rev 2, the littlest computer that could OpenCV.