IEI Released a New Fanless DIN-Rail Embedded system for AI Deep Learning – ITG-100AI

The ITG-100AI is pre-installed with a Mustang-MPCIE-MX2 AI accelerator card, which includes two Intel® Movidius™ Myriad™ X VPU, to provide a flexible AI inference solution.

VPU is short for vision processing unit. It can run AI faster, and is well suited for low power consumption applications such as surveillance, retail and transportation. With the advantage of power efficiency and high performance to dedicate Deep Neural Networks (DNN) topologies, it is perfect to be implemented in AI edge computing device to reduce total power usage, providing longer duty time for the rechargeable edge computing equipment.

Key Features of Intel® Movidius™ Myriad™ X VPU:

  • Native FP16 support
  • Rapidly port and deploy neural networks in Caffe and Tensorflow formats
  • End-to-End acceleration for many common deep neural networks
  • Industry-leading Inferences/S/Watt performance
Mustang-MPCIE-MX2
Mustang-MPCIE-MX2

Ultra-compact Size

Space limitation is one of the constraints commonly seen in today’s industrial environment. Under tight restrictions, the ITG-100AI-AL not only provides palm-sized design to meet the space requirement, but also comes with adequate basic I/O interfaces for various applications.

Features:

  • Intel®Atom™ x5-E3930 1.3GHz (up to 1.8 GHz)
  • Two GbE LAN ports
  • Two RS-232/422/485
  • M.2 A-key slot for expansion
  • Pre-installed Mustang-MPCIE-MX2, 2 x Intel Myriad X VPU for AI deep learning workload consolidation

The ITG-100AI is available now at an undisclosed price. More information may be found in IEI’s announcement and product page. More on the Mustang-MPCIE-MX2 module may be found on the Mustang-MPCIE-MX2 product page.

esp32MX-E, The New Chip on the Block

There are a host of boards based around the ESP32, and also its follow up, the ESP8266. It’s noteworthy to witness how they have evolved from the simple breakout boards they were when the chip was released back in 2015 to something a lot more major. The latest of these boards is the esp32MX-E from Modtronix Engineering, which will be raising soon on Crowd Supply.

Measuring at 64.4 × 42 mm (2.54 × 1.65 inch), the board is designed based on an off the shelf ESP-WROOM-32 module. One interesting feature is its independent methods of powering the board; a USB-C connector, a 2.1 mm barrel connector, or via broken-out +V and GND pins, the board can be powered with a 4.5 to 16 V supply. The on-board USB connector also enables a serial console, and allows you to program the board. The board offers both Wi-Fi, and Bluetooth, enabled by the ESP32, and also an Ethernet jack. The board also features a Micro SD card slot, along with a user addressable LED and button. The ESP32 board is built around a dual-core 32-bit Tensilica’s Xtensa LX6 micro-processor which operates at either 160 or 240 MHz, equipped with 4MB of SPI Flash, and 520KB of SRAM.

The board also has a user-programmable STMicroelectronicSTM32F030F4 micro-controller. The micro-controller is a 32-bit Arm Cortex-M0 core operating at 48 MHz, with 256 KB of Flash and 32 KB of SRAM. The I²C I/O secondary processor expander handles the pins on the two expansion headers; the first has 2×7 pins, and the other has 2×10 pins with programmable pull-up and pull-down resistors on most inputs. We should note that not all of the pins are available when the SD card slot is in use.

The board will be released in two versions, but with different operating range. While both will have the same configurations, one will have an operating range of 0° C to 85° C, while the second, an ‘industrial’ version, will operate at temperatures down to -40° C. The board is aimed squarely towards the Internet of Things (IoT) and industry, and will be housed in anonymous black or grey boxes with numbers written in sharpie on the outside for easy identification from other boxes.

Features & Specifications

  • esp32 Module
    • 32-bit LX6 microprocessor operating at 160 or 240 MHz
    • 4 MB Flash
    • 520 KB SRAM
  • Storage: Micro SD card slot
  • Wi-Fi: 802.11 b/g/n
  • Bluetooth: v4.2 BR/EDR and BLE
  • USB: Type C connector
    • Virtual com port via USB
    • Programmable via USB
    • Power via USB
  • User I/O:
    • 22 pins of which 4 are inputs only.
    • Four 5 V tolerant I/O pins
    • Not all I/Os are available when the SD Card is used
    • Programmable pull-up and pull-down resistors on most inputs
  • Secondary Processor: I²C I/O expander implemented with a user programmable STM32F030F4
  • Expansion Pin Headers: Two standard 2.54 mm (0.1″) expansion pin headers
    • One with 14 pins (2×7)
    • One with 20 pins (2×10)
  • Power Supply:
    • 5 V switch mode power supply capable of supplying over 2 A for user application
    • 3.3 V switch mode power supply capable of supplying over 2 A for user application
  • Power Sources:
    • USB Type C connector
    • 2.1 mm barrel connector
    • Vx external power supply pin
  • Supply Voltage: 4.5 to 16 V (via 2.1 mm Barrel connector or Vx pin)
  • Operating Temperature: 0° C to 85° C (Industrial version with -40° C to 85° C also available)
  • Physical Controls:
    • User LED
    • Button
  • Compact Size: 64.4 x 42 mm (2.54″ x 1.65″)
  • Enclosure: Optional

This board, and similar boards, are the quietly anonymous Windows XP boxes of the coming future. They are set to replace  ageing desktop machines that are found on factory floors the world over. With the inclusion of machine learning, this board is set to be a major choice for rapidly deployed distributed sensor network. It’s a primary indicator about how the market is shaping around computing that originated from the maker market. In other words, the esp32MX-E is an excellent example of a whole class of boards.

For now, the board is not available, but the esp32MX-E will be raising soon on Crowd Supply. You can sign up for email updates to be notified when the project goes live. Prices are not available yet, and won’t be until the Crowd Supply campaign starts.

60V to 5V @ 3.5A Buck converter with USB output

This is a 60V to 5V – 3.5A step down DC-DC converter based on TPS54360B from Texas Instruments. Sample applications are: 12 V, 24 V and 48 V industrial, Automotive and Communications Power Systems. The TPS54360 is a 60V, 3.5A, step down regulator with an integrated high side MOSFET. The device survives load dump pulses up to 65V per ISO 7637. Current mode control provides simple external compensation and flexible component selection. A low ripple pulse skip mode reduces the no load supply current to 146 μA. Shutdown supply current is reduced to 2 μA when the enable pin is pulled low.

60V to 5V @ 3.5A Buck converter with USB output – [Link]

60V to 5V @ 3.5A Buck converter with USB output

This is a 60V to 5V – 3.5A step down DC-DC converter based on TPS54360B from Texas Instruments. Sample applications are: 12 V, 24 V and 48 V industrial, Automotive and Communications Power Systems. The TPS54360 is a 60V, 3.5A, step down regulator with an integrated high side MOSFET. The device survives load dump pulses up to 65V per ISO 7637. Current mode control provides simple external compensation and flexible component selection. A low ripple pulse skip mode reduces the no load supply current to 146 μA. Shutdown supply current is reduced to 2 μA when the enable pin is pulled low.

Under-voltage lockout is internally set at 4.3 V but can be increased using the enable pin. The output voltage start up ramp is internally controlled to provide a controlled start up and eliminate overshoot. A wide switching frequency range allows either efficiency or external component size to be optimized. Frequency fold back and thermal shutdown protects internal and external components during an overload condition.

Note: The output voltage is set by a resistor divider from the output node to the FB terminal. It is recommended to use 1% tolerance or better divider resistors, choose R5, R6 for other output voltages.

It is strongly recommended to use adequate air flow over the board to ensure it doesn’t go at thermal shutdown. See thermal profile below.

Setting Output Voltage

The following table lists the R5 values for some common output voltages assuming R6= 10.0kΩ

Features

  • Supply Input 8.5V-60V
  • Output 5V (Output Voltage adjustable with R5, R6)
  • Output Current 3.5A
  • 100 kHz to 2.5 MHz Switching Frequency
  • Optional JST connector for 5V Fan
  • Current Mode Control DC-DC Converter
  • Integrated 90-mΩ High Side N-Channel MOSFET
  • High Efficiency at Light Loads with Pulse Skipping Eco-mode™
  • Low Dropout at Light Loads with Integrated BOOT Recharge FET
  • 146 μA Operating Quiescent Current
  • 1 µA Shutdown Current
  • Internal Soft-Start
  • Accurate Cycle-by-Cycle Current Limit
  • Thermal, Overvoltage, and Frequency Fold back Protection
  • PCB Dimensions 55.50mm x 24.64mm

Schematic

Parts List

PCB

Thermal Image

You can see on the thermal images below that at 60V input – 5V @2A output the IC gets too hot (>105ºC) and if we go for higher outputs (2.5-3A) the IC gets in thermal cut-off. To avoid this situation you can use a small 5V FAN to blow air on the board or probably use a heatsink attached to the board.

60V input – 5V @1A output
60V input – 5V @2A output
60V input – 5V @3A output cooled with a small FAN

Measurements

The efficiency is calculated based on the (Pout/Pin)*100%. For 60V input and 5V @3A output the input current is 0.32A, so Pin=19.38W. Pout=5V*3A=15W, so e=77.39% with Pdis = 4.58W

Output Ripple 60V input – 5V @1A output
Output Ripple 60V input – 5V @3A output
CH1: SW pin – CH2: Vout (60V input – 5V @3A output)
CH1: Vin – CH2: Vout (60V input – 5V output no load) – Start up
CH1: Vin – CH2: Vout (60V input – 5V @3A output) – Start up

Video

Photos

TPS54360B Datasheet

Board Viewer

New and Improved Geiger Counter – Now With WiFi!

In one of our previous tutorials, we examined the development of a DIY-Geiger Counter showing the efforts of “Instructable” user Prabhat who combined the ESP8266 with a touch screen display to create a truly intuitive version of his Geiger Counter. He recently created an updated version and today’s tutorial will focus on how this new version of the Geiger Counter can be replicated. The Geiger counter is an instrument used for detecting and measuring ionizing radiation. It is one of the worlds best-known radiation detection instrument as it can be used to detect ionizing radiation such as alpha particles, beta particles, and gamma rays and its is usually used as a handheld radiation survey instrument, warning users when in the region of dangerous ambient radiation levels with an all-too-familiar clicking noise.

While this project retains some of the features from the first version, like the use of the ESP8266 and a touchscreen interface, rather than just implementing the detection of  radiation levels like the first version, it combines a Geiger counter, a dosimeter and a radiation monitoring together in a single package that is 50% less thick, and with loads of new software features! Some of the new features include:

New and Improved Geiger Counter – Now With WiFi! – [Link]

ST730 – 300 mA, 28 V LDO, with 5 µA quiescent current

ST Microelectronics’ ST730 is a 300 mA LDO regulator designed to be used in several medium voltage applications. Ultra-low quiescent current of 5 µA makes it suitable for applications permanently connected to power supply and battery. This feature is also useful when electronic modules remain permanently turned on. The ST730 embeds protection functions, such as current limit, short-circuit, and thermal shutdown. The extended input voltage range, very low drop voltage, and low quiescent current features make it suitable also for low-power after-market automotive and consumer applications.

Key Features

  • Wide input voltage range : 2.5 V to 28 V
  • Ultra-low quiescent current: typ. 5 μA at no-load, 10 μA max. across full temperature range, 1 μA max. in shutdown
  • High output voltage accuracy: ± 0.5% @ 25 °C, ± 1% across temperature range
  • Output current up to 300 mA
  • Fixed output voltage versions, starting from 1.2 V to 12 V with 100 mV step
  • Adjustable voltage version, starting from 1.2 V to VIN – VDROP
  • Stable with low ESR capacitors (0.47 µF min.)
  • Thermal shutdown protection
  • Current limit and SOA protection
  • -40 °C to +125 °C operating temperature range

more: www.st.com

AK09970D Ultra-Small Tri-Axis Magnetic Smart Switch

AKM’s AK09970D has 1/5 of the packaging area of the conventional AK09970N

AKM’s AK09970D is a device with a much smaller overall footprint than its conventional tri-axis magnetic smart switch sensor, the AK09970N. Mobile devices, such as smartphones and various wearable devices, can be equipped with this sensor that requires low power consumption and a high degree of freedom in placement. Applications include open/close, stroke, rotation, and push detection in mobile devices.

The AK09970D has a high sensitivity setting of 36mT on tri-axis. It is able to measure a wide range of magnetic field from microtesla to millitesla such as from geomagnetic to a magnet since it has high measurement resolution of 1.1µT/LSB in high sensitivity mode. In addition, wide range setting of 101mT can be achieved via the Z axis.

The AK09970D can operate using only a few µA, thus consuming a very low current that satisfies a demand of IoT products, (Refer to the Specification Table). It contributes to a long battery life of a product that needs constant acquisition of sensor data to monitor an object’s status.

The AK09970D measures magnetic field on all tri-axis via intermittent drive and outputs the result as digital data, (supporting I2C communications). It outputs a Data Ready alert to the dedicated register when the measurement data is updated. (0.25/0.5/1/10/20/50/100Hz interval modes or single measurement mode is selectable for intermittent drive options.)

The AK09970D has magnetic event interrupt pin. Two thresholds can be programmed for each axis, (setting the resolution equal to the measuring resolution). When a magnetic field that exceeds the threshold is sent, the AK09970D outputs a “Magnetic Event” interrupt to external output pin.

Features

  • Wide input voltage range: 2.5 V to 28 V
  • Ultra-low quiescent current: typ. 5 µA at no-load, 10 µA max. across full temperature range
  • Output current up to 300 mA
  • High output voltage accuracy: ±0.5% @ 25 °C, ±1% across temperature range

more: www.akm.com & s-cube.akm.com

Binho Multi-Protocol USB Host Adapter supports I2C, SPI, 1wire and more

The new Binho multi-protocol USB host adapter powered by the USB connection to a host PC allows you to interface your computer directly to hardware circuits. 

The Binho adapter has support for 12C @ 3.4 MHz max clock, SPI @12MHz max clock, Dallas 1wire, Atmel single wire interface, UART @ 1000000 max baud as well as support for ADC functionality. It also has a single-channel DAC output that can help in case you need to stimulate your circuit with a particular voltage. While in IO mode, its 5 signal pins can serve as digital input or output, digital interrupt, PWM output, or analog input or output while the remaining pins assigned to other related or unrelated purposes.

Some of the key features and details of the USB host adapter include:

  • Provides 3v3 and VUSB power rails
  • 1 DAC outputs and 5 ADC inputs
  • Programmable RGB status LED
  • Cross platform support for Windows, Linux and Mac.
  • Support for GPIO/Interrupt/PWM
  • USB Type-C connector
  • Low-profile aluminum enclosure
  • Field upgradeable device firmware

With the Binho adapter, there is no constraint to a particular Operating System environment as the drivers are already included for most OS. The cross-platform software available for Mac, Windows and Linux, provides an easy-to-use GUI interface for your USB host adapter. The device is also able to provide downstream power to test circuits; for convenience’s sake, it makes available power source from the 3v3 rail or the 5V USB Bus power.

The Binho Multi-Protocol USB Host Adapter brings USB Host Adapters into the 21st Century. No more fumbling through development with cumbersome, clunky, out-dated adapters. Let your productivity soar to new heights!

The Binho multi-protocol USB host adapter is commonly used for development and testing purposes. It is used in production environment for some functional testing in Flash and EEPROM memory programming. It is also ideal for manual testing during system debugging and firmware development as well as to automate hardware testing.

Built to last, Binho multi-protocol USB host adapter is covered completely against any malfunction or defect. Its anodized aluminum enclosure and low profile design makes it safe and easy to carry around.

With its robust package and support for multiple protocols all in one slim, Binho has become one of the most versatile USB host adapter available. The adapter aims at increasing productivity during development and it comes alongside a one foot USB Type C (male) to Type A (male) cable and a breadboard break out adapter in a soft-shell zippered case.

More information can be found on Binho’s website. It is currently being sold for $149.00 and shipping is done within 24 hours.

NanoPi R1S Dual Gigabit Ethernet Router Comes with 32-bit or 64-bit ARM Processor

FriendlyELEC launched NanoPi R1 SBC & Gateway earlier this year with Allwinner H3 processor, two Ethernet ports, as well as WiFi and Bluetooth connectivity. The design makes use of both Ethernet on the processor, but that also means on Gigabit Ethernet port had to be combined with a Fast Ethernet processor.

The company has now added a USB to Gigabit Ethernet bridge to their latest NanoPi R1S board meaning it’s now a dual Gigabit Ethernet SBC, but with the caveat that the port behind the USB bridge is limited to USB 2.0 speed (480 Mbps), and with overhead the USB Ethernet bandwidth is around 330 Mbps.

There are two versions of the board, namely NanoPi R1S-H3 and R1S-H5 with respectively Allwinner H3 32-bit processor, and Allwinner H5 64-bit processor.

Apart from the different processors, both boards share the same PCBA and specifications:

  • SoC
    • NanoPi R1S-H3 – Allwinner H3 quad-core Arm Cortex-A7 processor @ up to 1.2GHz with Mali-400MP2 GPU
    • NanoPi R1S-H5 – Allwinner H5 quad-core Arm Cortex-A53 processor @ up to 1.2GHz with Mali-450MP GPU
  • System Memory – 512MB DDR3 RAM
  • Storage – MicroSD Slot, SPI flash footprint
  • Connectivity
    • 1x “true” Gigabit Ethernet (WAN)
    • 1x “USB 2.0” Gigabit Ethernet (LAN) up to around 330 Mbps
    • 802.11b/g/n WiFi 4 with IPX-I antenna connector
  • USB – 1x USB Type-A host port, 1x micro USB port
  • Debugging – 3-pin 2.54mm pitch header for serial console
  • Misc – 3x LEDs (WAN, LAN, SYS), K1 reset button, fan header
  • Power Supply – DC 5V/3A via micro USB port
  • Dimensions – 55.6 x 52mm
  • Temperature Range – -20℃ to 70℃

The company does not currently sell the barebone board , and instead, NanoPi R1S is sold as a router with a yellow enclosure (no other colors available) running either FriendlyWrt based on OpenWrt or FriendlyCore based on Ubuntu 18.04, both shipping with Linux 4.14.

You’ll find more technical details and links to the respective firmware files on the Wikis for R1S-H3 and R1S-H5 routers. Cooling is achieved with a heatsink that covers a large part of the board.

NanoPi R1S-H3 router is sold for $19.99, while NanoPi R1S-H3 goes for $3 more, and both are available on the same page on FriendlyELEC shop. I understand the prices include the board, heatsink and enclosure, and you can purchase a 16GB MicroSD card, 5V/3A power supply, and/or micro USB cable as options.

via www.cnx-software.com

New and Improved Geiger Counter – Now With WiFi!

In one of our previous tutorials, we examined the development of a DIY-Geiger Counter showing the efforts of “Instructable” user Prabhat who combined the ESP8266 with a touch screen display to create a truly intuitive version of his Geiger Counter. He recently created an updated version and today’s tutorial will focus on how this new version of the Geiger Counter can be replicated.

The Geiger counter is an instrument used for detecting and measuring ionizing radiation. It is one of the worlds best-known radiation detection instrument as it can be used to detect ionizing radiation such as alpha particles, beta particles, and gamma rays and its is usually used as a handheld radiation survey instrument, warning users when in the region of dangerous ambient radiation levels with an all-too-familiar clicking noise.

While this project retains some of the features from the first version, like the use of the ESP8266 and a touchscreen interface, rather than just implementing the detection of radiation levels like the first version, it combines a Geiger counter, a dosimeter, and a radiation monitoring together in a single package that is 50% less thick, and with loads of new software features! Some of the new features include:

  • A more intuitive GUI
  • Displays counts per minute, current dose, and accumulated dose on the home screen
  • Sensitive and reliable SBM-20 Geiger-Muller tube
  • Variable integration time for averaging dose rate
  • Timed count mode for measuring low doses
  • Users can choose between Sieverts and Rems as the units for the displayed dose rate
  • User-adjustable alert threshold
  • Adjustable calibration to relate CPM to dose rate for various isotopes
  • Offline data logging
  • Post bulk-logged data to a cloud service (ThingSpeak) to graph, analyze and/or save to computer
  • Monitoring Station mode: device stays connected to WiFi and regularly posts ambient radiation level to ThingSpeak channel
  • 2000 mAh rechargeable LiPo battery with a 16 hour run time and a micro USB charging port
  • No programming required from the end-user as things like the WiFi setup is handled through the user interface.

While most of these upgrades will not make sense to a non-radiation nerd, the updates take the device to a more powerful level when compared with some of the regular Geiger counter available in the market.

Wemos D1 mini board
Wemos D1 mini board

The ESP8266 was retained from the previous version, but a Wemos D1 mini was used in place of the NodeMCU to reduce the overall size of the project. The SBM-20 Geiger Muller tube and the 2.8″ SPI touchscreen were also retained. Several other discrete components were used with most of them being of SMD types to make the device compact.

At the end of this tutorial, you would know not only how to replicate this project but how to implement tasks like; building IoT Devices capable of uploading data to Thingspeak, update WiFi details using a GUI without changing the code and so many other fascinating things.

Required Components

The components required in making the full assembly of the project are provided in the list below. The list does not include the discrete components which will be provided in a table so things are not messy.

  1. WEMOS D1 Mini or clone
  2. 2.8″ SPI Touchscreen
  3. SBM-20 Geiger tube with it’s ends taken off (many vendors online)
  4. 3.7 V LiPo charger board
  5. Turnigy 3.7 V 1S 1C LiPo battery (49 x 34 x 10mm) with JST-PH connector 
  6. M3 x 22 mm Countersunk screws
  7. M3 x 8 mm hex machine screws
  8. M3 brass threaded insert
  9. Conductive copper tape

SMB-20 Tube Electrical Specifications:

  • Operating voltage: 350 to 475 V DC
  • Minimum anode resistor: 1 MΩ (voltage rating at least 500 V)
  • Recommended anode resistor: 5.1 MΩ (voltage rating at least 500 V)
  • Plateau length: at least 100 V
  • Plateau slope: 0.1% per 1 V
  • Minimum dead time: 190 μs (at 400V)

SMB-20 Tube Physical specifications

  • Diameter: 11 mm
  • Length: 108 mm (+/- 2.5 mm)
  • Weight: 10 g
  • Temperature rating: -60 to +70°C

Other discrete components used are provided in the table below and the entire BOM is attached as a .CSV file under the download section.

A table containing discrete components used

All discreet components used for the project were purchased from LCSC.com, so entering the part numbers in the LCSC search bar will show the exact components.

Schematics

The project was implemented using a PCB to make things compact and tidy. As mentioned earlier, most of the electronic parts used are SMD types, and this was done to reduce the size of the device as much as possible. The schematic for the project is designed by Prabhat and it is provided below:

To make it easier for those who may want to make modifications or reproduce the PCB, all of the project files including the schematics and PCB which were developed using Kicad, have been included in the zip file under the download section and can also be downloaded from Prabhat’s GitHub page.

All passive components (resistors, capacitors) were implemented with a 1206 footprint, while the transistors were implemented with SOT-23, LDO in SOT-89, and 555 timers in SOIC-8. Custom footprints were made for the inductor, switch and the buzzer and the required files for them are also zipped with the other files under the download section.

PCB

The PCB after fabrication will look like the image below;

Enclosure Design

A change in the design and placement of components between the two versions means we will also need to create another enclosure for today’s project.

This enclosure was designed to match the new reduced size of the device. It contains fewer parts (just two) compared to the first version and screws are still used in its assembly. Rather than placing the Geiger Muller tube in the top part like the first version, it was placed on the sides of the enclosure to remove the need for additional space at the top of the device.

The .STL files of all parts of the enclosure are attached in the zip file under the download section.

Enclosure 3D View

Loading file
  • Fullscreen
  • Wireframe
  • Zoom In
  • Zoom Out
  • Rotation
  • Screenshot
  • Help

Controls

×
  • Rotate with the left mouse button.
  • Zoom with the scroll button.
  • Adjust camera position with the right mouse button.
  • Double-click to enter the fullscreen mode.
  • On mobile devices swipe to rotate.
  • On mobile devices pinch two fingers together or apart to adjust zoom.
  • On mobile devices 3 finger horizontal swipe performs panning.
  • On mobile devices 3 finger horizontal swipe performs panning.

Setup Thingspeak

As mentioned during the introduction, this version of the project will have the ability to operate in 3 modes, either as a Datalogger, Monitoring station or as the ordinary Geiger Counter. When used as a data logger or monitoring station, the device is sending it’s data to the cloud and for that reason, Thingspeak was used as the device cloud platform. As such, it is important to create a Thingspeak account and obtain all necessary credentials like; API key and Channel ID as they will be required when the project is being further developed.

Follow the steps below to set up your Thingspeak account;

1. Go to Thingspeak and signup or sign-in if you already have an account.

2. After logging in, click on the channels button. This will lead you to the channels page. The channels page provides you with a list of all the channels you have created. Click on the add new channel button to add a new one.

3. This will lead you to a page where you are expected to fill in the details of the channel. Enter the Name, a short description, and fields. For this project, we will create two channels. The first one will hold “Logged counts per minute” data with a field to hold the “CPM”.
4. While the second one will hold “Live Updates of CPM” data with a field called “Live updates“. Click on the OK button after filling the details.

5. The two channels should now be added to your channel list like the image below.

6. By clicking on each of the channels, you will be redirected to the dashboard for that channel where you will see it’s channel ID. Copy the channel ID for both channels as we will use them in our code.

7. On the channel dashboard, also click on API keys. This should show you the API keys to both read and write to the channel. Copy and keep the Write API key since our intention is to write to the channel.

With this done we now have all we need to write the code.

Device Assembly

Follow the steps below to put the device together after the PCB has been assembled.

  1. Start by soldering all SMD components to the Main PCB first, using either a Hot Air Soldering station or reflow oven
  2. Also, Solder the battery charger board to the pads and the through-hole components to the main PCB.
  3. Remove the SD card reader from the LCD display to prevent it from interacting with the Process during data logging.
  4. Solder the LCD board to the PCB AT THE END. You won’t be able to de-solder the D1 Mini after this. Another option is to install the D1 mini using header pins, so there won’t be a need to solder it and it will be possible to remove it at will.
  5. Ensure there are no protruding LEDs and that all components were properly soldered.
  6. Take two pieces of stranded wire and solder one end of the first wire to one end (Anode) of the SBM-20, and connect one end of the second wire to the body of the SBM-2o holding it in place with copper tape. Connect the other end of the two wires to the anode and cathode connections (respectively) on the board. Take care to ensure the polarity is correct.
  7. 3D print the case and the cover, and arrange the components inside the case securing the assembled PCB with 3.8mm Screws. Also, place the Geiger tube beside the grill and tape it to prevent it from falling off. Connect all the wires, along with the battery and close up the enclosure using the cover. You should now be ready to go.

After assembling, the device should look like the image below before the back cover is mounted.

Assembled Geiger Counter

Code

Just like with the previous version, the code for this version is also developed using “PlatformIO IDE“. This means, if you didn’t go through the platformIO.org set up during the last tutorial, you have another chance to get it done now. Follow the tutorial we created a while back on how to Program the Arduino and ESP8266 Boards with Platform.io, to get it sorted.

The sketch for this project is heavily reliant on the Adafruit_ILI9341, the Adafruit GFX, the WiFi Manager library. The ILI9341 library allows us to directly interact with the display as it was used to create the user interface for the display, while the WiFi manager allows users to change the password stored on the device without making any changes to the code, removing the need to edit the code to add WiFi Credentials. Asides these libraries, we will use several other libraries like; the XPT2046_Touchscreen library, the EEPROM library, the SPI library among others.  The XPT2046_touchscreen library allows us to use the touchscreen features of the display while the EEPROM library, on the other hand, allows us perform the same tasks it was used for in the first version; to save all the settings including WiFi credentials such that when power is recycled, the data is not lost and users won’t need to supply that information again. All of these libraries can be installed via the Arduino library manager.

The sketch is quite similar to the one for our last tutorial but as usual, I will do a quick explanation of some of the important parts of the code.

We start by declaring the libraries that will be used. In addition to the libraries mentioned above, we will add a couple of font libraries for use in displaying text on the display.

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <EthernetClient.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WifiManager.h>
#include <EEPROM.h>
#include "SPI.h"
#include "Adafruit_GFX.h"
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include "Adafruit_ILI9341.h"
#include <XPT2046_Touchscreen.h>

Next, we create an object of the touchscreen library with the CS pin as an argument and then create variables to hold the (4 extremes) calibration points for the touch screen and specify the pins of the Arduino to which the DC and CS pins of the display are connected.

#define CS_PIN D2
XPT2046_Touchscreen ts(CS_PIN);

#define TS_MINX 250
#define TS_MINY 200 // calibration points for touchscreen
#define TS_MAXX 3800
#define TS_MAXY 3750

#define TFT_DC D4
#define TFT_CS D8

We also create variables to hold the hex values signifying the different colors that we will be using after which we create variables to hold various WiFi/data upload parameters like the password, SSID, API key and channel ID as obtained from Thingspeak, Thingspeak server address among others.

#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define DOSEBACKGROUND 0x0455

// WiFi variables
unsigned long currentUploadTime;
unsigned long previousUploadTime;
int passwordLength;
int SSIDLength;
int channelIDLength;
int writeAPILength;
char ssid[20];
char password[20];
char channelID[20]; // = "864288";
char channelAPIkey[20]; // = "37SAHQPEQ7FOBC20";
char server[] = "api.thingspeak.com";
int attempts; // number of connection attempts when device starts up in monitoring mode

Next, we create a WiFi through which the device will communicate over the web, and we create an instance of the Adafruit TFT library.

WiFiClient client;

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

Other variables that will be used for data logging on Thingspeak, monitoring the battery, saving data in the EEPROM, and calculating the dosing units are then created.

const int interruptPin = 5;

long count[61];
long fastCount[6]; // arrays to store running counts
long slowCount[181];
int i = 0;         // array elements
int j = 0;
int k = 0;

int page = 0;

long currentMillis;
long previousMillis;
unsigned long currentMicros;
unsigned long previousMicros;

unsigned long averageCount;
unsigned long currentCount;  // incremented by interrupt
unsigned long previousCount; // to activate buzzer and LED
unsigned long cumulativeCount;
float doseRate;
float totalDose;
char dose[5];
int doseLevel;               // determines home screen warning signs
int previousDoseLevel;

bool ledSwitch = 1;
bool buzzerSwitch = 1;
bool wasTouched;
int integrationMode = 0; // 0 = medium, 1 = fast, 2 == slow;

bool doseUnits = 0; // 0 = Sievert, 1 = Rem
unsigned int alarmThreshold = 5;
unsigned int conversionFactor = 175;

int x, y; // touch points

// Battery indicator variables
int batteryInput;
int batteryPercent;
int batteryMapped = 212;       // pixel location of battery icon
int batteryUpdateCounter = 29;

// EEPROM variables
const int saveUnits = 0;
const int saveAlertThreshold = 1; // Addresses for storing settings data in the EEPROM
const int saveCalibration = 2;
const int saveDeviceMode = 3;
const int saveLoggingMode = 4;
const int saveSSIDLen = 5;
const int savePWLen = 6;
const int saveIDLen = 7;
const int saveAPILen = 8;

// Data Logging variables
int addr = 200;                 // starting address for data logging
char jsonBuffer[14000] = "["; 
char data[14500] = "{\"write_api_key\":\"";
unsigned long currentLogTime;
unsigned long previousLogTime;


// Timed Count Variables:
int interval = 5;
unsigned long intervalMillis;
unsigned long startMillis;
unsigned long elapsedTime;
int progress;
float cpm;
bool completed = 0;
int intervalSize; // stores how many digits are in the interval

// Logging variables
bool isLogging;

bool deviceMode;

// interrupt routine declaration
void ICACHE_RAM_ATTR isr();

unsigned int previousIntMicros;              // timers to limit count increment rate in the ISR

Next, we create variables that are used to hold the Char equivalent of different bitmap images. We covered how to generate this in a previous tutorial we did on displaying bitmap images on LCDs.

const unsigned char gammaBitmap [] PROGMEM = {
  0x30, 0x00, 0x78, 0x70, 0xe8, 0xe0, 0xc4, 0xe0, 0x84, 0xc0, 0x05, 0xc0, 0x05, 0x80, 0x07, 0x80, 
  0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x3e, 0x00, 
  0x1c, 0x00, 0x00, 0x00
};

const unsigned char betaBitmap [] PROGMEM = {
  0x00, 0xc0, 0x00, 0x03, 0xf0, 0x00, 0x07, 0x18, 0x00, 0x06, 0x18, 0x00, 0x0e, 0x18, 0x00, 0x0e, 
  0x18, 0x00, 0x0e, 0xf8, 0x00, 0x0e, 0x1c, 0x00, 0x0e, 0x0c, 0x00, 0x0e, 0x0c, 0x00, 0x0e, 0x0c, 
  0x00, 0x0e, 0x0c, 0x00, 0x0f, 0x1c, 0x00, 0x0f, 0xf8, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 
  0x0c, 0x00, 0x00, 0x00, 0x00, 0x00
};
const unsigned char wifiBitmap [] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x0f, 0xfe, 0x00, 0x3f, 0xff, 0x80, 0x78, 
  0x03, 0xc0, 0xe0, 0x00, 0xe0, 0x47, 0xfc, 0x40, 0x0f, 0xfe, 0x00, 0x1c, 0x07, 0x00, 0x08, 0x02, 
  0x00, 0x01, 0xf0, 0x00, 0x03, 0xf8, 0x00, 0x01, 0x10, 0x00, 0x00, 0x40, 0x00, 0x00, 0xe0, 0x00, 
  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

const unsigned char settingsBitmap[] PROGMEM = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x00,
    0x00, 0x01, 0xc0, 0x7f, 0xe0, 0x38, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x7f, 0xe0, 0xfc, 0x00, 0x00,
    0x00, 0x07, 0xf9, 0xff, 0xf9, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
    0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
    0x00, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00,
    0x00, 0x03, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00,
    0x00, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0, 0x7f, 0xfc, 0x00, 0x00,
    0x00, 0x03, 0xff, 0xc0, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x00,
    0x00, 0xff, 0xff, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x01, 0xff, 0xff, 0x00, 0x07, 0xff, 0xf8, 0x00,
    0x01, 0xff, 0xfe, 0x00, 0x07, 0xff, 0xf8, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x07, 0xff, 0xf8, 0x00,
    0x01, 0xff, 0xfe, 0x00, 0x07, 0xff, 0xf8, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x07, 0xff, 0xf8, 0x00,
    0x01, 0xff, 0xfe, 0x00, 0x07, 0xff, 0xf8, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0xff, 0xf0, 0x00,
    0x00, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x00, 0x00, 0x03, 0xff, 0xc0, 0x3f, 0xfc, 0x00, 0x00,
    0x00, 0x03, 0xff, 0xe0, 0x7f, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00,
    0x00, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00,
    0x00, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00,
    0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
    0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xf9, 0xff, 0xf9, 0xfe, 0x00, 0x00,
    0x00, 0x03, 0xf0, 0x7f, 0xe0, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x7f, 0xe0, 0x38, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

const unsigned char buzzerOnBitmap[] PROGMEM = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x0c, 0x00,
    0x00, 0x00, 0x07, 0x80, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x80,
    0x07, 0x00, 0x00, 0x00, 0x3f, 0x80, 0xc7, 0x80, 0x00, 0x00, 0xff, 0x80, 0xe3, 0x80, 0x00, 0x01,
    0xff, 0x80, 0xf3, 0xc0, 0x00, 0x03, 0xff, 0x80, 0x71, 0xc0, 0x00, 0x07, 0xff, 0x8c, 0x79, 0xc0,
    0x3f, 0xff, 0xff, 0x9e, 0x38, 0xe0, 0x3f, 0xff, 0xff, 0x8e, 0x38, 0xe0, 0x3f, 0xff, 0xff, 0x8e,
    0x3c, 0xe0, 0x3f, 0xff, 0xff, 0x87, 0x1c, 0xe0, 0x3f, 0xff, 0xff, 0x87, 0x1c, 0x60, 0x3f, 0xff,
    0xff, 0x87, 0x1c, 0x70, 0x3f, 0xff, 0xff, 0x87, 0x1c, 0x70, 0x3f, 0xff, 0xff, 0x87, 0x1c, 0x70,
    0x3f, 0xff, 0xff, 0x87, 0x1c, 0x70, 0x3f, 0xff, 0xff, 0x87, 0x1c, 0x70, 0x3f, 0xff, 0xff, 0x87,
    0x1c, 0xe0, 0x3f, 0xff, 0xff, 0x8e, 0x3c, 0xe0, 0x3f, 0xff, 0xff, 0x8e, 0x38, 0xe0, 0x3f, 0xff,
    0xff, 0x9e, 0x38, 0xe0, 0x00, 0x07, 0xff, 0x8c, 0x79, 0xc0, 0x00, 0x03, 0xff, 0x80, 0x71, 0xc0,
    0x00, 0x00, 0xff, 0x80, 0xf1, 0xc0, 0x00, 0x00, 0x7f, 0x80, 0xe3, 0x80, 0x00, 0x00, 0x3f, 0x80,
    0xc7, 0x80, 0x00, 0x00, 0x1f, 0x80, 0x07, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x0f, 0x00, 0x00, 0x00,
    0x07, 0x80, 0x0e, 0x00, 0x00, 0x00, 0x03, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

const unsigned char buzzerOffBitmap[] PROGMEM = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80,
    0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00,
    0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00,
    0x00, 0x03, 0xff, 0x80, 0x00, 0x00, 0x00, 0x07, 0xff, 0x80, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x80,
    0x00, 0x00, 0x0f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff,
    0xff, 0x8f, 0x00, 0x78, 0x7f, 0xff, 0xff, 0x8f, 0x80, 0xf8, 0x7f, 0xff, 0xff, 0x8f, 0xc1, 0xf8,
    0x7f, 0xff, 0xff, 0x87, 0xe3, 0xf0, 0x7f, 0xff, 0xff, 0x83, 0xf7, 0xe0, 0x7f, 0xff, 0xff, 0x81,
    0xff, 0xc0, 0x7f, 0xff, 0xff, 0x80, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x80, 0x7f, 0x00, 0x7f, 0xff,
    0xff, 0x80, 0x7f, 0x00, 0x7f, 0xff, 0xff, 0x80, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x81, 0xff, 0xc0,
    0x7f, 0xff, 0xff, 0x83, 0xf7, 0xe0, 0x7f, 0xff, 0xff, 0x87, 0xe3, 0xf0, 0x7f, 0xff, 0xff, 0x8f,
    0xc1, 0xf0, 0x7f, 0xff, 0xff, 0x8f, 0x80, 0xf8, 0x3f, 0xff, 0xff, 0x8f, 0x00, 0x70, 0x3f, 0xff,
    0xff, 0x84, 0x00, 0x20, 0x1f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x80, 0x00, 0x00,
    0x00, 0x07, 0xff, 0x80, 0x00, 0x00, 0x00, 0x03, 0xff, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x80,
    0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00,
    0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00,
    0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

const unsigned char ledOnBitmap[] PROGMEM = {
    0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x07, 0x00, 0xc0, 0x00, 0x00, 0x1c, 0x07, 0x01, 0xc0, 0x00, 0x00, 0x1e,
    0x07, 0x03, 0xc0, 0x00, 0x00, 0x0e, 0x07, 0x03, 0x80, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x80, 0x00,
    0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x1e, 0x00, 0x1f, 0xc0, 0x03, 0xc0, 0x0f, 0x80, 0x7f, 0xf0, 0x0f, 0x80, 0x07, 0xc1,
    0xff, 0xfc, 0x1f, 0x00, 0x03, 0xc3, 0xe0, 0x3e, 0x1e, 0x00, 0x00, 0x07, 0xc0, 0x0f, 0x00, 0x00,
    0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x80, 0x00, 0x00, 0x0e, 0x00, 0x03,
    0x80, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x80, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0, 0x00, 0x7f, 0x1c,
    0x00, 0x01, 0xc3, 0xf0, 0x7f, 0x1c, 0x00, 0x01, 0xc7, 0xf0, 0x3c, 0x0e, 0x00, 0x03, 0x81, 0xe0,
    0x00, 0x0e, 0x00, 0x03, 0x80, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x80, 0x00, 0x00, 0x0f, 0x00, 0x07,
    0x80, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0f, 0x00, 0x00, 0x01, 0xc3,
    0xc0, 0x1e, 0x1c, 0x00, 0x07, 0xc1, 0xc0, 0x1c, 0x1f, 0x00, 0x0f, 0x81, 0xe0, 0x3c, 0x0f, 0x80,
    0x1e, 0x00, 0xe0, 0x38, 0x03, 0xc0, 0x0c, 0x00, 0xe0, 0x38, 0x01, 0x80, 0x00, 0x00, 0xf0, 0x78,
    0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00,
    0x3f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00,
    0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0,
    0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00};

const unsigned char ledOffBitmap[] PROGMEM = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x01,
    0xff, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x3e, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x0f, 0x00, 0x00,
    0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x80, 0x00, 0x00, 0x0e, 0x00, 0x03,
    0x80, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x80, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x1c,
    0x00, 0x01, 0xc0, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x80, 0x00,
    0x00, 0x0e, 0x00, 0x03, 0x80, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x80, 0x00, 0x00, 0x0f, 0x00, 0x07,
    0x80, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x03,
    0xc0, 0x1e, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x1c, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x3c, 0x00, 0x00,
    0x00, 0x00, 0xe0, 0x38, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x38, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x78,
    0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00,
    0x3f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00,
    0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0,
    0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00};

const unsigned char backBitmap [] PROGMEM = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 
    0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 
    0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

Next, we declare all the functions that we will use. It is important to note that this may not be necessary but it just prevents errors that may be experienced with certain C/C++ compilers.

void drawHomePage();              // page 0
void drawSettingsPage();          // page 1
void drawUnitsPage();             // page 2
void drawAlertPage();             // page 3
void drawCalibrationPage();       // page 4
void drawWifiPage();              // page 5
void drawTimedCountPage();        // page 6
void drawTimedCountRunningPage(int duration, int size); // page 7 
void drawDeviceModePage();        // page 8

void drawFrame();
void drawBackButton();
void drawCancelButton();
void drawCloseButton();
void drawBlankDialogueBox();

long EEPROMReadlong(long address);
void EEPROMWritelong(int address, long value); // logging functions
void createJsonFile();
void clearLogs();

With that done, we then move to the void setup() function.

We start the void setup() function by initializing the serial monitor setting our baud rate to 38400. Feel free to set this to whatever you want, only ensure the serial monitor is set to the same baud rate.

void setup()
{
  Serial.begin(38400);

We then initialize the touchscreen(ts) and the TFT using the begin command and we set the rotation to an orientation that suits us (2 in this case). We also fill the screen with a black color to create a sort of black background.

ts.begin();
ts.setRotation(2);

tft.begin();
tft.setRotation(2);
tft.fillScreen(ILI9341_BLACK);

With that done, we initialize the pins to which the status LED and the buzzer are connected, setting their pin modes to output and turning both off.

pinMode(D0, OUTPUT); // buzzer switch
pinMode(D3, OUTPUT); // LED
digitalWrite(D3, LOW);
digitalWrite(D0, LOW);

We follow that up by initializing the EEPROM and initializing a couple of variables including doseUnits, alarmThreshold and conversionFactor , deviceMode, SSIDLength, Channel ID, etc., using data stored on the EEPROM.

EEPROM.begin(4096);   // initialize emulated EEPROM sector with 4 kb

doseUnits = EEPROM.read(saveUnits);
alarmThreshold = EEPROM.read(saveAlertThreshold);
conversionFactor = EEPROM.read(saveCalibration);
deviceMode = EEPROM.read(saveDeviceMode);
isLogging = EEPROM.read(saveLoggingMode);
addr = EEPROMReadlong(96);

SSIDLength = EEPROM.read(saveSSIDLen);
passwordLength = EEPROM.read(savePWLen);
channelIDLength = EEPROM.read(saveIDLen);
writeAPILength = EEPROM.read(saveAPILen);

The SSIDLength, passwordLength, ChannelIDlength, and writeAPILength are then used as pointers to fetch the SSID, Password, ChannelID, and APIkey, respectively, from the EEPROM.

for (int i = 10; i < 10 + SSIDLength; i++)
  {
    ssid[i - 10] = EEPROM.read(i);
  }
  Serial.println(ssid);

  for (int j = 30; j < 30 + passwordLength; j++)
  {
    password[j - 30] = EEPROM.read(j);
  }
  Serial.println(password);

  for (int k = 50; k < 50 + channelIDLength; k++)
  {
    channelID[k - 50] = EEPROM.read(k);
  }
  Serial.println(channelID);

  for (int l = 70; l < 70 + writeAPILength; l++)
  {
    channelAPIkey[l - 70] = EEPROM.read(l);
  }
  Serial.println(channelAPIkey);

Next, we call the drawHomePage() function to display the home page.

drawHomePage();

To wrap up the void setup(), we check to see if a mode was selected for the device. if no mode was selected, the ESP8266 WiFi features are turned off. But if a mode was selected, the WiFi details are set and the connection progress and status are displayed. Another instance of the drawHomePage is called after the device is successfully connected to the internet.

if (!deviceMode)
  {
    WiFi.mode( WIFI_OFF );                // turn off wifi
    WiFi.forceSleepBegin();
    delay(1);
  }
  else
  {
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    drawBlankDialogueBox();
    tft.setTextSize(1);
    tft.setFont(&FreeSans9pt7b);
    tft.setTextColor(ILI9341_WHITE);
    
    tft.setCursor(38, 140);
    tft.println("Connecting to WiFi..");

    while ((WiFi.status() != WL_CONNECTED) && (attempts < 300))
    {
      delay(100);
      attempts ++;
    }
    if (attempts >= 300)
    {
      deviceMode = 0; 
      tft.setCursor(45, 200);
      tft.println("Failed to connect.");
      delay(1000);
    }
    else
    {
      tft.setCursor(68, 200);
      tft.println("Connected!");
      delay(1000);
    }
    drawHomePage();
  }
}

With that done, we then move to the void setup function.

Next is the void loop function. This is where all the action takes place. The void loop is definitely too long to explain but thanks to the very descriptive variable names that were used, it should be easy to follow. The basic idea is to monitor the dose adjusted parameter which is influenced by the dose rate which is in turn by the activities taking place in the GM tube. When the dose level attains a particular threshold, it triggers the alarm and displays the current critical level of radiation being experienced. There is also a part of the void loop code that creates a JSON file with the readings obtained from the device and uploads it to Thingspeak either at regular intervals or whenever WiFi/internet access is available. Other code snippets in the void loop function are related to displaying data and maintaining the good UI on the display.

Due to its bulkiness, the complete code for the project is attached along with other resources under the download section.

Programming

Compiling and upload of the code are done using the PlatformIO IDE as mentioned above. This is a new generation toolset for embedded C/C++ development that you need to install to use the code above. You will need first to download and install the Microsoft’s Visual Studio Code as PlatformIO IDE is built on top of it. To do so follow the short instructions here. Then re-launch the Visual Studio Code to apply the changes. You will now see the PlarformIO extension active as in the screen below:

PlarformIO installed on Microsoft Visual Studio Code

Next click “New Project” -> Add a project name -> Select board: WeMos D1 mini Lite  -> Framework: Arduino -> Finish. You will then see a list of directories and files on the left. Select the main.cpp and paste the code found above in the editor. Now it’s time to compile the code and check if everything is fine. Before you do I would advise adding: #include <Wire.h> library in the list of headers as this is needed during compiling. Also, be sure to install the necessary libraries from the library manager:

PlatformIO Library Manager

The libraries needed are:

  • Adafruit GFX Library
  • Adafruit ILI9341
  • Adafruit TouchScreen
  • WifiManager
  • XPT2046_Touchscreen

In our case, we had to manually download Adafruit_TouchScreen library and place it in the following path:

C:\Users\<your username>\.platformio\lib

as the library from the build-in manager didn’t work for us. Now it’s time to compile the code using the “Build” button. If everything is fine the code should compile successfully.

Successful Build

Next, we are ready to upload the code to our WeMos D1 board. To do so click the “Upload” button at the bottom of the page. Wait for a few seconds and the code will successfully be uploaded.

Demo

You should now see the screen come up with the home page being displayed as shown in the image below.

Testing the Geiger Counter with various radioactive sources

To test the device, some radiation sources were placed next to it and it was detected as shown in the video below:

Oscilloscope Measurements

Yellow: The voltage spike from a γ-photon detection on the cathode of the tube. Green: the INT signal produced from the impulse detection circuit that drives the D1 pin of WeMos D1
same as above without the measurement markers for better visibility
Yellow: The voltage spike from a γ-photon detection on the anode of the tube (we see the voltage drop from 278V to almost half) Green: the INT signal produced from the impulse detection circuit that drives the D1 pin of WeMos D1
The discharge voltage on 555 timer IC pin 6

 

Improvements

The Geiger Plateau Curve (source wikimedia.org)

While the Geiger counter seems to work fine for detecting hard β and γ photons, we should note that the tube working voltage can go as high as 280Vdc using the above 555 timer oscillator. This voltage is below the recommended operating voltage (350 – 475V) for the SBM-20 tube and seems to operate out of the plateau region (100V length) where the tube’s response is flat. So, we would recommend improving the high voltage power supply to a source that can generate higher voltages. This will help to operate the tube on the manufacture recommended voltage.

Conclusion

The GC-20 comes with several new features that allow users to make several changes to the configuration/setup via the user interface, and to make it easy to follow, Prabhat created a user manual for the device to show how it is used. Going through the manual might also help offer better insight into how the code works.

The improvements and features inculcated into the Geiger counter by Prabhat makes it more desirable compared to the regular ones in the market and this goes to show the power of improvement which DIY can bring to a project.

All project files are attached under the download section and do feel free to reach out to me via the comment section if you had any difficulty replicating the project.

A video demo of the project by Prabhat can be found on Youtube.

References:

TOP PCB Companies