A Student designed ESP8266 Dev Board


This is a student-designed ESP8266 Dev board. This project came along after I challenged some final-year students at our local high school to try to design their own PCBs. They had recently assisted me in a collaboration with the Mushroom House Controller project, and while we were talking about electronics, the idea of a challenge came up, to stimulate some interaction.

One of them was extremely confident that he could do it, providing that I gave him a schematic. I complied, and he spent the next week hacking away on the EDA software. When i saw him again, he very proudly handed me a USB flash drive, containing the EDA design, but no schematic! Oh well, let us take a chance and see what happens… I mean, how bad could it be…

I took a good look at the design, making sure that it was at least electrically sound, with all the connections made to the right components, in the right way.

That part all passed, but, as we can clearly see, the layout could be very much improved. I decided to NOT change anything on the PCB, to keep the work original.

Manufacturing the PCB

The PCB, together with a stencil, arrived from PCBWay on about the 15th of this month.

I choose PCBWay for my PCB manufacturing. Why? What makes them different from the rest?

PCBWay‘s business goal is to be the most professional PCB manufacturer for prototyping and low-volume production work in the world. With more than a decade in the business, they are committed to meeting the needs of their customers from different industries in terms of quality, delivery, cost-effectiveness and any other demanding requests. As one of the most experienced PCB manufacturers and SMT Assemblers in China, they pride themselves to be our (the Makers) best business partners, as well as good friends in every aspect of our PCB manufacturing needs. They strive to make our R&D work easy and hassle-free.

How do they do that?

PCBWay is NOT a broker. That means that they do all manufacturing and assembly themselves, cutting out all the middlemen, and saving us money.

PCBWay’s online quoting system gives a very detailed and accurate picture of all costs upfront, including components and assembly costs. This saves a lot of time and hassle.

PCBWay gives you one-on-one customer support, that answers you in 5 minutes ( from the Website chat ), or by email within a few hours ( from your personal account manager). Issues are really resolved very quickly, not that there are many anyway, but, as we are all human, it is nice to know that when a gremlin rears its head, you have someone to talk to who will do his/her best to resolve your issue as soon as possible.

Find out more here

Assembly

The PCB was assembled with help of a stencil.

Technically, this PCB does not actually need it, as the components are large enough to manually place solder paste. This being a student project, I did however choose to get the stencil to try and assure the best possible chance of success..

Placing components only took a few minutes, after which the PCB was reflowed with hot air – no need for a hotplate here!

Through-hole components took only another few minutes to solder into place, and then testing could commence.

My thoughts – a very “gentle” critique

The board could be smaller, but due to the fact that this is a “very first PCB ever” and also a first SMD PCB at that, I can understand that it may still be quite difficult to understand how small the components really are, as well as lay them out properly.

Components are mostly all over the board, without a clear “group by function” kind of mindset. This once again comes back to experience.

GPIO pins are not notated. This will really make the board difficult to use.
The power supply input is in the center of the PCB. This is definitely not ideal.

In general, track sizes could have been bigger, especially on the Power and Ground lines. No ground plane was poured on either layer.

So does it work?
Yes, surprisingly it does. We shall see more of it in the near future, when I task the creator with using it to perform some task. That way, he can experience first hand the difficulties of the design, and also learn practically why certain things need to be improved.

A Simple IoT Plant Watering Solution

This is a Simple IoT Plant Watering Solution, done as another collaboration with the local High School in my Area. In this project, they took a group of purely academic students ( Language majors ) and told them that they had to design an electronics project that would have use in the real world…

This presented a very tough situation to the students since they had never even imagined that they could do something like this… (Think along the lines of a Senior Design project, like what you would give EE Students during their final year – with all the documentation, pamphlets, and explanations – i.e. lots and lots of paperwork) , and then also add on the requirement that they had to present a practical project as well! And they have only 45 days to do that as well!

I came into this picture late on a Thursday or Friday afternoon, with a group of students milling around outside the Electronics lab. They were unknown to me and seemed quite flustered… I invited them in, and eventually, they started opening up about their problem…

As it turned out, they were completely clueless, and did not know where to start with anything, not even what they wanted to do! Their initial idea went like “something that uses a camera to sort garbage by type and material” – that was never going to happen, not in 45 days, and not with the allocated budget of no more than $USD30.00 they were allowed. Lets not even go to the machine learning stuff, training of the models etc…

So, I took over, and decided that we shall do a simple IoT Plant Watering Solution. It is complex enough for Grade 11 students, and more importantly, I knew that I could teach them enough Arduino coding and basic electronics skills in the time allotted to get the project completed successfully.

What followed was a few very intensive sessions after school to get the paperwork sorted. For some reason, their teacher required ALL paperwork be completed upfront, with the entire design and code prepared before they touched the practical stuff – A funny way to design stuff if you ask me, but that is how we did it…

We settled on the ESP8266 12-E NodeMCU v3 development board, A resistive soil sensor, a DHT11 for temperature and humidity data, a small OLED I2C display and a small 5v USB-powered water pump. While they ordered the components, we started with basic coding classes, and this is where the story changes.

These kids blew me away with their level of interest, their attitude to learning, and how quickly they grasped the concepts. In no time at all, they were coding basic sketches, taking readings, learning how the different sensors worked, and pushing the envelope by adding lots more complementary components like MOSFETs and BJT transistors.


With this level of enthusiasm, I could not help but also become very excited, and thus decided to go a bit further than usual and help them design a neat PCB baseboard for the NodeMCU. That way, we could get rid of all those pesky wire connections, and maybe even produce something that looked good.


This is what we came up with, here shown just after SMD component placing. They ( the students ) did all of that by themselves as well, and it turned out to be a lot of fun for them, with some funny moments for me as well.

The Assembly ( First time ever )

The PCB, together with a stencil, arrived from PCBWay on about the 15th of this month.

I choose PCBWay for my PCB manufacturing. Why? What makes them different from the rest?

PCBWay‘s business goal is to be the most professional PCB manufacturer for prototyping and low-volume production work in the world. With more than a decade in the business, they are committed to meeting the needs of their customers from different industries in terms of quality, delivery, cost-effectiveness and any other demanding requests. As one of the most experienced PCB manufacturers and SMT Assemblers in China, they pride themselves to be our (the Makers) best business partners, as well as good friends in every aspect of our PCB manufacturing needs. They strive to make our R&D work easy and hassle-free.

How do they do that?

PCBWay is NOT a broker. That means that they do all manufacturing and assembly themselves, cutting out all the middlemen, and saving us money.

PCBWay’s online quoting system gives a very detailed and accurate picture of all costs upfront, including components and assembly costs. This saves a lot of time and hassle.

PCBWay gives you one-on-one customer support, that answers you in 5 minutes ( from the Website chat ), or by email within a few hours ( from your personal account manager). Issues are really resolved very quickly, not that there are many anyway, but, as we are all human, it is nice to know that when a gremlin rears its head, you have someone to talk to who will do his/her best to resolve your issue as soon as possible.

Find out more here

This caused quite a lot of excitement from the students since they asked me to get to school immediately, and offered to stay after school to get the assembly done. So, I packed up all the components required, got in the car, and a few minutes later, we had an assembly line running 🙂


It took them only a few minutes to understand how to read the BOM file, use that information to find the right components and take turns to place a few components at a time onto the PCB. ( I did the solder paste and stencil thing on my own, as that could potentially turn out to be a very messy and wasteful operation if I let them do it )

During this assembly, they were quite amazed at what they were doing, but also quite confused as to how we would ” make the components stick to the PCB later”. They have seen soldering on YouTube, and could not understand how this “grey paste” could “turn hard and shiny” – with some even trying to rush their friends, as the paste would dry up and become sticky…

That signalled to me that we should get the hot air ready, and show them properly, as it would stop the speculation, and give them closure on their questions, because no matter how much I tried to explain that the solder paste would be melted later, they could not understand that concept.


Once I reflowed the first few components using hot air, they all once again took turns with a small group of components on the PCB ( We assembled 2 PCB’s to make sure everybody got a chance to try everything)


Through-hole soldering of the various header pins and other components was next. Once again, I showed them an example and then stepped back while they took over and completed the task. At this time it was about 17:30 already, so I sent them all home, with a promise to return the next day and complete the rest of the build.

Final Assembly and the Enclosure


We added some copper standoffs to the bottom of the enclosure, drilled some holes and mounted everything with screws and hot glue. The some final testing was performed, and the project was placed outside, next to a potted plant, and put on a sort of soak test, to verify operation for a few days.

A discussion of the circuit

In this circuit, I made use of a very cheap resistive soil moisture probe sensor. It consists of an etched PCB probe and a separate OPAMP on an additional PCB. This assembly then sends an analog voltage back to the Microprocessor for analysis. Very easy to use, and as mentioned, extremely cheap! But this is also a big problem. As seen in many other posts online, people don’t like these probes, as they don’t seem to last very long, and/or become unreliable over time.

I believe that this is due to the fact that they run them continuously, and that, causes the electrodes to erode away over time – because the thing about it, you are basically running an electrolysis cell – sending voltage/current through a probe, that is suspended in a conductive medium ( the water in the soil contains minerals etc – that is why it is conductive, and why we can get a reading from it )

How do I plan to avoid this problem then? The probe is powered through a small N-Channel MOSFET. This allows us to power the probe on when we want a reading, and then power it off again. It will definitely not completely stop the electrodes eroding away over time, but I am sure it will extend the usable lifetime of the probe by quite a bit. On the downside, you need another GPIO pin to control that MOSFET, but that in itself is also a great learning opportunity

Code

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32


#define DHTTYPE    DHT11     // DHT 11
#define WaterRelay 2
#define A0Enable 14
#define DHTEnable 13
#define DHTPIN 12
#define WATER_DELAY 10000
#define WATER_LOW 20.00
#define SOIL_DELAY 5000

uint32_t delayMS;
float temperature = 0.00;
float humidity = 0.00;
float soilValue = 0.00;
float soilAverage = 0.00;
unsigned long previousMillis = 0;
unsigned long previousWater = 0;
unsigned long previousSoil = 0;
bool MAY_WATER = 0;
bool RUN_WATER = 0;
bool DELAY_WATER = 0;
sensor_t sensor;
const String WaterOn = "Waterpump ON";
const String WaterOff = "Waterpump OFF";
String WaterMessage = "";

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
DHT_Unified dht(DHTPIN, DHTTYPE);



void setup() {
  
  pinMode(WaterRelay,OUTPUT);
  pinMode(A0Enable,OUTPUT);
  pinMode(DHTEnable,OUTPUT);
  digitalWrite(WaterRelay,HIGH);
  //Serial.begin(115200);
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    //Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  display.ssd1306_command(SSD1306_DISPLAYON);
  display.clearDisplay();
  display.display();
  delay(20);
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10,10);
  display.print("Booting...");
  display.display();
  delay(2000);
  
  dht.begin();
  
  show_DHT_Params();
  
}

void loop() {
  
  
  

  //Soil Monitor Loop
  unsigned long SoilMillis = millis();
  if ( SoilMillis - previousSoil >= SOIL_DELAY) {
    previousSoil = SoilMillis;
    take_soil_reading();
  }
  //End Soil Monitor Loop

  //Water Loop
  unsigned long WaterMillis = millis();
  if (WaterMillis - previousWater >= WATER_DELAY) {
    previousWater = WaterMillis;
    if ((digitalRead(WaterRelay) == LOW) && (RUN_WATER == 1) && ( DELAY_WATER == 0)) {
      digitalWrite(WaterRelay,HIGH);
      DELAY_WATER = 1;
    } else if (DELAY_WATER == 1) {
      DELAY_WATER = 0;
      if (RUN_WATER == 1) RUN_WATER = 0;
    }
  }
  // End Water Loop
  // Main One Second Delay Loop
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= delayMS) {
    previousMillis = currentMillis;
    get_DHT_Readings();
    show_Soil_Data();
    display.display();
  }
  // End Main 1 Second Loop
  if ((soilAverage < WATER_LOW) && (RUN_WATER == 0)) {
    RUN_WATER = 1;
    MAY_WATER = 1;
  } else if (soilAverage >= WATER_LOW) {
    RUN_WATER = 0;
    MAY_WATER = 0; 
  }

  if ((digitalRead(WaterRelay) == HIGH) && (RUN_WATER == 1) && DELAY_WATER == 0) {
      digitalWrite(WaterRelay,LOW);
      WaterMessage = WaterOn;
      take_soil_reading();
  }
  if ((DELAY_WATER == 1) && (MAY_WATER == 1)) {
      digitalWrite(WaterRelay,HIGH);
      WaterMessage = WaterOff;
  }
  
}

void take_soil_reading() {
  digitalWrite(A0Enable,HIGH);
  delay(50);
  
  float tempSoil = 0.00;
  for (int i = 0; i <10 ; i++) {
    soilValue = (1024.00 - analogRead(A0));
    tempSoil = tempSoil + soilValue;
    delay(2);
  }
  soilAverage = map(tempSoil/10,0.00,1023.00,0.00,100.00);
  delay(30);
  digitalWrite(A0Enable,LOW);
}

void show_DHT_Params() {
  digitalWrite(DHTEnable,HIGH);
  
  dht.temperature().getSensor(&sensor);
  display.clearDisplay();
  display.display();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10,1);
  display.print("Temperature Sensor");
  display.setCursor(10,10);
  display.print(F("Type: "));
  display.print(sensor.version);
  display.setCursor(10,20);
  display.print(F("Min: "));
  display.print(sensor.min_value);
  display.print(F(" Deg C"));
  display.setCursor(10,30);
  display.print(F("Max: "));
  display.print(sensor.max_value);
  display.print(F(" Deg C"));
  display.setCursor(10,40);
  display.print(F("Resolution: +/- "));
  display.setCursor(10,50);
  display.print(sensor.resolution);
  display.print(F(" Deg C"));
  display.display();
  delay(4000);
  dht.humidity().getSensor(&sensor);
  display.clearDisplay();
  display.display();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10,1);
  display.print("Humidity Sensor");
  display.setCursor(10,10);
  display.print(F("Type: "));
  display.print(sensor.version);
  display.setCursor(10,20);
  display.print(F("Min: "));
  display.print(sensor.min_value);
  display.print(F(" % RH"));
  display.setCursor(10,30);
  display.print(F("Max: "));
  display.print(sensor.max_value);
  display.print(F(" % RH"));
  display.setCursor(10,40);
  display.print(F("Resolution: +/- "));
   display.setCursor(10,50);
  display.print(sensor.resolution);
  display.print(F(" % RH"));
  display.display();
  delay(4000);
  
  delayMS = sensor.min_delay / 1000;
}

void get_DHT_Readings() {
    
    display.clearDisplay();
    display.setTextSize(2);
    display.setTextColor(SSD1306_WHITE);
    sensors_event_t event;
    dht.temperature().getEvent(&event);
    if (isnan(event.temperature)) {
      #ifdef DEBUG-SERIAL
      Serial.println(F("Error reading temperature!"));
      #endif
    }
    else {
      display.setCursor(10,1);
     
      display.setCursor(10,1);
      display.print(event.temperature);
      display.setCursor(80,1);
      display.println(F(" C"));
      temperature = event.temperature;
    }
    // Get humidity event and print its value.
    dht.humidity().getEvent(&event);
    if (isnan(event.relative_humidity)) {
     display.clearDisplay();
    display.setTextSize(2);
    display.setTextColor(SSD1306_WHITE);
    sensors_event_t event;
    dht.temperature().getEvent(&event);
    if (isnan(event.temperature)) {
      #ifdef DEBUG-SERIAL
      Serial.println(F("Error reading temperature!"));
      #endif
    }
    else {
      
      display.setCursor(10,1);
      display.print(event.temperature);
      display.setCursor(80,1);
      display.println(F(" C"));
      temperature = event.temperature;
    }
    // Get humidity event and print its value.
    dht.humidity().getEvent(&event);
    if (isnan(event.relative_humidity)) {
      #ifdef DEBUG-SERIAL
      Serial.println(F("Error reading humidity!"));
      #endif
    }
    else {
      display.setCursor(10,20);
      display.print(event.relative_humidity);
      display.setCursor(80,20);
      display.println(F(" %"));
      humidity = event.relative_humidity;
    }
    }
    else {
      display.setCursor(10,20);
      display.print(event.relative_humidity);
      display.setCursor(80,20);
      display.println(F(" %RH"));
      humidity = event.relative_humidity;
    }
    
}

void show_Soil_Data() {
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10,39);
  display.print(soilAverage);
  display.setCursor(80,39);
  display.println(F(" %"));
  display.setTextSize(1);
  display.setCursor(10,56);
  display.println(WaterMessage);
}

Conclusion

This project was extremely interesting. It was something very basic, but it gave me a very unique opportunity to teach a group of kids something they never knew before. It also initiated a spark in many of them, who are now interested in getting involved in electronics as a hobby. The possibilities of this project, if it is improved a bit more, could also be great. For example, we did not even consider adding IoT connectivity to this yet, we all decided that it was not needed, and an unnecessary complication of an already complex issue ( to the students that is). I shall keep monitoring the operation of the device over the next few weeks, and hopefully get some answers myself as to how long that soil probe will last… As a control, we have another one that was left powered on in the same container. That one are not being used to take readings, but will definitely provide us with a good comparison against the probe that is only on then used…

XIAO RP2040 Mouse Ver 3.0

Over the last few months, We have been steadily improving the design of our XIAO RP2040-based mouse device. With this, ver 3.0 all the hardware bugs were finally eliminated, and we also placed the device into its first-ever enclosure.

Let us take a look at the design

The PCB and Schematic


The PCB is a very strange shape, with lots of cut-outs. This is to accommodate the big push buttons that will be mounted in the enclosure, as well as to fit nicely into the mounting area of the enclosure… This design took quite some time with a pair of callipers and CAD, but all went well, and the shape is perfectly accurate.


The schematic is also straight forward, with the only real changes begin to the rotary encoder. In ver 2.0, We connected the encoder to the MCP23008, but for some reason CircuitPython does not seem to like an encoder connected to an IO extender… That forced us to do some software hack to use the encoder… I have thus decided to change things around in ver 3.0 and move the encoder back to the native GPIO on the XIAO RP2040

It is also interesting to note that the circuit was initially designed for the XIAO ESP32S3, but due to issues with stock, as well as crazy prices on local parts, we made a quick turn-around and went back to the RP2040. The ESP32S3 was going to allow us to implement a wireless device, through using ESPNow protocol… That may still be done in future, but for now, I think we have done enough work on the mouse device for the time being…

Manufacturing the PCB and Assembly

I choose PCBWay for my PCB manufacturing. Why? What makes them different from the rest?

PCBWay‘s business goal is to be the most professional PCB manufacturer for prototyping and low-volume production work in the world. With more than a decade in the business, they are committed to meeting the needs of their customers from different industries in terms of quality, delivery, cost-effectiveness and any other demanding requests. As one of the most experienced PCB manufacturers and SMT Assemblers in China, they pride themselves to be our (the Makers) best business partners, as well as good friends in every aspect of our PCB manufacturing needs. They strive to make our R&D work easy and hassle-free.

How do they do that?

PCBWay is NOT a broker. That means that they do all manufacturing and assembly themselves, cutting out all the middlemen, and saving us money.

PCBWay’s online quoting system gives a very detailed and accurate picture of all costs upfront, including components and assembly costs. This saves a lot of time and hassle.

PCBWay gives you one-on-one customer support, that answers you in 5 minutes ( from the Website chat ), or by email within a few hours ( from your personal account manager). Issues are really resolved very quickly, not that there are many anyway, but, as we are all human, it is nice to know that when a gremlin rears its head, you have someone to talk to who will do his/her best to resolve your issue as soon as possible.

Find out more here


Assembly was quite easy, I chose to use a stencil, because the IO Expander chip has a very tiny footprint, as well as a leadless package… The stencil definitely helps prevent excessive solder paste, as well as saves a lot of time on reworking later…


In the picture above, we can clearly see why I had to design the PCB with such an irregular shape.

Firmware and Coding

We are still using CircuitPython for the firmware on this device. It is not perfect, but it works, well sort of anyway. What does that mean? Well… As far as the mouse functions are concerned, clicking, scrolling, moving the pointer – all of that is works perfectly, and thus allows me to use the device for basic operations every day. Drag and Drop, as well as selecting and or highlighting text DOES NOT work. This seem to be an issue with the HID code in Circuitpython, meaning it doesn’t seem to be implemented. It is also way beyond my abilities to implement it myself…

Below is the code.py file, with the boot.py below that


import time
import board
import busio
from rainbowio import colorwheel
import neopixel
import rotaryio
import microcontroller
from digitalio import Direction
from adafruit_mcp230xx.mcp23008 import MCP23008
import digitalio
i2c = busio.I2C(board.SCL, board.SDA)
mcp = MCP23008(i2c)


from analogio import AnalogIn
import usb_hid
from adafruit_hid.mouse import Mouse
joyX = board.A0
joyY = board.A1
JoyBtn = board.D2

LeftBtn = 0
CenterBtn = 1
RightBtn = 2
UpBtn = 3
DownBtn = 4
EncoderBtn = 5


mouse = Mouse(usb_hid.devices)
xAxis = AnalogIn(joyX)
yAxis = AnalogIn(joyY)

# NEOPIXEL
pixel_pin = board.NEOPIXEL
num_pixels = 1
pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.1, auto_write=False)

leftbutton = mcp.get_pin(LeftBtn)
leftbutton.direction = digitalio.Direction.INPUT
leftbutton.pull = digitalio.Pull.UP

centerbutton = mcp.get_pin(CenterBtn)
centerbutton.direction = digitalio.Direction.INPUT
centerbutton.pull = digitalio.Pull.UP

maint_btn = digitalio.DigitalInOut(JoyBtn)
maint_btn.switch_to_input(pull=digitalio.Pull.UP)

rightbutton = mcp.get_pin(RightBtn)
rightbutton.direction = digitalio.Direction.INPUT
rightbutton.pull = digitalio.Pull.UP

enc_btn = mcp.get_pin(EncoderBtn)
enc_btn.direction = digitalio.Direction.INPUT
enc_btn.pull = digitalio.Pull.UP

scroll_up = mcp.get_pin(UpBtn)
scroll_up.direction = digitalio.Direction.INPUT
scroll_up.pull = digitalio.Pull.UP

scroll_down = mcp.get_pin(DownBtn)
scroll_down.direction = digitalio.Direction.INPUT
scroll_down.pull = digitalio.Pull.UP



mousewheel = rotaryio.IncrementalEncoder(board.D6, board.D7, 4)
last_position = mousewheel.position
print(mousewheel.position)

move_speed = 3
enc_down = 0

RED = (255, 0, 0)
YELLOW = (255, 150, 0)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)
BLACK = (0, 0, 0)


if move_speed == 0:
    in_min, in_max, out_min, out_max = (0, 65000, -20, 20)
    filter_joystick_deadzone = (
        lambda x: int((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)
        if abs(x - 32768) > 500
        else 0
    )
if move_speed == 1:
    pixels.fill(GREEN)
    pixels.show()
    in_min, in_max, out_min, out_max = (0, 65000, -15, 15)
    filter_joystick_deadzone = (
        lambda x: int((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)
        if abs(x - 32768) > 500
        else 0
    )
if move_speed == 2:
    pixels.fill(BLUE)
    pixels.show()
    in_min, in_max, out_min, out_max = (0, 65000, -10, 10)


filter_joystick_deadzone = (
        lambda x: int((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)
        if abs(x - 32768) > 500
        else 0
    )
if move_speed == 3:
    pixels.fill(PURPLE)
    pixels.show()
    in_min, in_max, out_min, out_max = (0, 65000, -8, 8)
    filter_joystick_deadzone = (
        lambda x: int((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)
        if abs(x - 32768) > 500
        else 0
    )
if move_speed == 4:
    pixels.fill(CYAN)
    pixels.show()
    in_min, in_max, out_min, out_max = (0, 65000, -5, 5)
    filter_joystick_deadzone = (
        lambda x: int((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)
        if abs(x - 32768) > 500
        else 0
    )


pixels.fill(BLACK)
pixels.show()
while True:
    # Set mouse accelleration ( speed)
    #print(mousewheel.position)
    if move_speed == 0:
        pixels.fill(BLACK)
        pixels.show()
        in_min, in_max, out_min, out_max = (0, 65000, -20, 20)
        filter_joystick_deadzone = (
            lambda x: int(
                (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
            )
            if abs(x - 32768) > 500
            else 0
        )
    if move_speed == 1:
        pixels.fill(GREEN)
        pixels.show()
        in_min, in_max, out_min, out_max = (0, 65000, -15, 15)
        filter_joystick_deadzone = (
            lambda x: int(
                (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
            )
            if abs(x - 32768) > 500
            else 0
        )
    if move_speed == 2:
        pixels.fill(BLUE)
        pixels.show()
        in_min, in_max, out_min, out_max = (0, 65000, -10, 10)
        filter_joystick_deadzone = (
            lambda x: int(
                (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
            )
            if abs(x - 32768) > 500
            else 0
        )
    if move_speed == 3:
        pixels.fill(PURPLE)
        pixels.show()
        in_min, in_max, out_min, out_max = (0, 65000, -8, 8)
        filter_joystick_deadzone = (
            lambda x: int(
                (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
            )
            if abs(x - 32768) > 500
            else 0
        )
    if move_speed == 4:
        pixels.fill(CYAN)
        pixels.show()
        in_min, in_max, out_min, out_max = (0, 65000, -5, 5)
        filter_joystick_deadzone = (
            lambda x: int(
                (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
            )
            if abs(x - 32768) > 500
            else 0
        )

    current_position = mousewheel.position
    position_change = current_position - last_position

    x_offset = filter_joystick_deadzone(xAxis.value) * -1  # Invert axis
    y_offset = filter_joystick_deadzone(yAxis.value)
    mouse.move(x_offset, y_offset, 0)

    if enc_btn.value and enc_down == 1:
        move_speed = move_speed + 1
        if move_speed > 4:
            move_speed = 0

        # print (move_speed)
        enc_down = 0

    if not enc_btn.value:
        enc_down = 1

    if leftbutton.value:
        mouse.release(Mouse.LEFT_BUTTON)
        # pixels.fill(BLACK)
        # pixels.show()
    else:
        mouse.press(Mouse.LEFT_BUTTON)
        pixels.fill(GREEN)
        pixels.show()

    if centerbutton.value:
        mouse.release(Mouse.MIDDLE_BUTTON)
    else:
        mouse.press(Mouse.MIDDLE_BUTTON)
        pixels.fill(YELLOW)
        pixels.show()

    # Center button on joystick
    if maint_btn.value:
        mouse.release(Mouse.LEFT_BUTTON)
    else:
        mouse.press(Mouse.LEFT_BUTTON)
        pixels.fill(GREEN)
        pixels.show()

    if rightbutton.value:
        mouse.release(Mouse.RIGHT_BUTTON)
        # pixels.fill(BLACK)
        # pixels.show()
    else:
        mouse.press(Mouse.RIGHT_BUTTON)
        pixels.fill(PURPLE)
        pixels.show()

    if not scroll_up.value:
        mouse.move(wheel=1)
        time.sleep(0.25)
        pixels.fill(BLUE)
        pixels.show()

    if not scroll_down.value:
        mouse.move(wheel=-1)
        time.sleep(0.25)
        pixels.fill(CYAN)
        pixels.show()

    if not scroll_up.value and not scroll_down.value:
        for x in range(4):
            pixels.fill(RED)
            pixels.show()
            time.sleep(0.5)
            pixels.fill(BLACK)
            pixels.show()
            time.sleep(0.5)
        microcontroller.reset()



    if position_change > 0:
        mouse.move(wheel=position_change)
        #print(current_position)
        #pixels.fill(BLUE)
        #pixels.show()
    elif position_change < 0:
        mouse.move(wheel=position_change)
        #print(current_position)
        #pixels.fill(CYAN)
        #pixels.show()
    last_position = current_position
    pixels.fill(BLACK)
    pixels.show()

boot.py

import storage
import board, digitalio
import time
from rainbowio import colorwheel
import neopixel
import busio
from digitalio import Direction
from adafruit_mcp230xx.mcp23008 import MCP23008
import digitalio
i2c = busio.I2C(board.SCL, board.SDA)
mcp = MCP23008(i2c)



#button = digitalio.DigitalInOut(board.D8)
#button.pull = digitalio.Pull.UP

button = mcp.get_pin(6)
button.direction = digitalio.Direction.INPUT
button.pull = digitalio.Pull.UP

Rstbutton = mcp.get_pin(7)
Rstbutton.direction = digitalio.Direction.INPUT
Rstbutton.pull = digitalio.Pull.UP

# NEOPIXEL
pixel_pin = board.NEOPIXEL
num_pixels = 1
pixels = neopixel.NeoPixel(pixel_pin,num_pixels,brightness=0.2,auto_write=False)

RED = (255, 0, 0)
YELLOW = (255,150, 0)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)
BLACK = (0, 0, 0)

# Disable devices only if button is not pressed.
#usb_hid.enable((), boot_device=2)
if button.value:
   pixels.fill(GREEN)
   pixels.show()
   storage.disable_usb_drive()
   usb_cdc.disable()
else:
    pixels.fill(RED)
    pixels.show()
    usb_cdc.enable(console=True, data=False)
    storage.enable_usb_drive()


time.sleep(5)
# Write your code here :-)

Assembling the Mushroom House Controller – Part 2

A Collaboration with Maesai Prasisart School, Measai, Chiang Rai, Thailand


In part two of the project, we let the students assemble the Mushroom house controller that they helped to design. It is important to note that they have never done any of this before, and also that most of the components are SMD.

This made for some interesting moments…

The PCB Arrives

The PCB arrived from the factory, and after an initial inspection by myself, we took it to the school so that a specially selected group of students can try their hand at assembling it.


One of the first remarks by the students was that everything was so tiny… Having never seen SMD assembly, they wrongly assumed that they would be required to manually solder the components using traditional solder and a soldering iron… This feeling of “dismay” was greatly increased when we started laying out the small bags with components.

I choose PCBWay for my PCB manufacturing. Why? What makes them different from the rest?

PCBWay‘s business goal is to be the most professional PCB manufacturer for prototyping and low-volume production work in the world. With more than a decade in the business, they are committed to meeting the needs of their customers from different industries in terms of quality, delivery, cost-effectiveness and any other demanding requests. As one of the most experienced PCB manufacturers and SMT Assemblers in China, they pride themselves to be our (the Makers) best business partners, as well as good friends in every aspect of our PCB manufacturing needs. They strive to make our R&D work easy and hassle-free.

How do they do that?

PCBWay is NOT a broker. That means that they do all manufacturing and assembly themselves, cutting out all the middlemen, and saving us money.

PCBWay’s online quoting system gives a very detailed and accurate picture of all costs upfront, including components and assembly costs. This saves a lot of time and hassle.

PCBWay gives you one-on-one customer support, that answers you in 5 minutes ( from the Website chat ), or by email within a few hours ( from your personal account manager). Issues are really resolved very quickly, not that there are many anyway, but, as we are all human, it is nice to know that when a gremlin rears its head, you have someone to talk to who will do his/her best to resolve your issue as soon as possible.

Find out more here

The Assembly



To make things easier for them, I had previously selected all components, and together with a label and component designators, placed each component into a separate anti-static plastic bag. This achieved two things – it shielded the students from having to handle reels of components, potentially resulting in a lot of wastage, and it make it almost impossible to place a wrong component in a wrong place, as each of the bags were clearly marked with the specific component designator of the component it contained.


Their feelings of “dismay” were quickly replaced with wonder as I used a stencil to apply solder paste to the PCB. There were also confusing present, as they could not understand how the “sticky” solder would melt and keep the component in place. They were also quite worried about placing the components onto the PCB – that was until they saw that there was a selection of fine tweezers set out to use for exactly this purpose…

They now became very excited and took turns to each place a few components onto the PCB. I took special care to keep the diodes, optic isolators and microcontroller well away from them, at least until I explained that these components were polarised, or had to be placed in a specific orientation onto the board.

After a bit of struggling with the diodes, as well as the microcontroller, all the SMD components were eventually correctly placed onto the PCB. I now took over and used a hotplate to reflow the PCB.


This process completely amazed them, or at least, most of them, as some took this opportunity to continue with the ever present interaction of students and mobile phones that are so common in SE Asia 🙂

The PCB was now reflowed, and after a short break to let things cool down, we continued with the soldering and assembly of the through-hole components.


The proceedings would not be complete without a group photo of the students and the PCB that they assembled.

Conclusion of part 2

With the PCB now assembled, I used my desktop CNC machine to cut acrylic plastic to form a protective shell. The PCB will soon be installed at the remote site shown in part 1, and while it will be inside a IP65 electrical enclosure, I still felt the need for a little bit of added protection.

The firmware development is complete, and we are currently busy bringing the students up to date with the exact operation thereof. Our goal is that they would at least try to create their own version of the firmware for use in the electronics lab, as well as a comparison between my version of the firmware and theirs.

From the smiles on their faces during the entire process, it was quite obvious that they really enjoyed this project.

Mushroom House Controller – Part 1

A Collaboration with Maesai Prasisart School, Maesai, Chiang Rai, Thailand


A short while ago, the local high school in my area and myself decided to collaborate on a real-world project regarding an IoT device. The device (prototype above) will be used as a controller in an Oyster Mushroom growing house, which in turn will be managed by the members of a local disabled persons association. This is very exciting for a few reasons…

I will get the opportunity to teach interested students how to solve real-world problems using electronics, as well we will do something for the community and thus contribute to making the lives of the local disabled people a bit easier.

In the long term, the data collected by the device can be used to teach other mushroom growers in the area about the optimum environment to help them ensure that they get the perfect harvest every time…

In this post, I will thus do things a little differently from my normal setup, and focus more on the collaboration, as well as teaching moments. I shall also include quite a lot of pictures. The usual schematics and PCB descriptions shall still be available, but only on the PCBWay Shared projects page ( link to be added in due course)

The initial idea is to produce two different PCB’s with basically the same function, for the time being designed by myself. One, used in this post, will be a 3.3v version, with battery backup, and the other will be a 5v version, with level converters ( I could not resist the potential teaching opportunity that these provided) and no battery backup. The 5v version, which I shall introduce in part 2 will be assembled by the students, while I shall assemble the 3.3v version.

Further to that, the goal is to break the PCB up into logical modules and teach the students about each module. Their task would be to then design a PCB of that module, and in the end, combine all the modules into a functional project.
As a further part to this, a special interest group shall then make use of the knowledge learnt during the development of the modules to design a third PCB including all of those modules, as well as any other that they find may be needed, assemble it and use it in the real world.

Gallery – At the remote site

Over here, Grade 12 students assist in the construction of a mushroom house.
The pictures do not need a lot of captions, as they are quite self-explanatory

The next day, in the classroom

We started with a prototype on a breadboard, with some basic firmware. This was followed by a simple PCB design (with frequent 3D views so that the students could see what was happening)


This was followed by a practical session where the students had the opportunity to try their hand at designing a part of the PCB. It is quite important that we understand that this is the very very first time in their lives that they were ever exposed to this. They were all extremely excited and some grasped the concepts quite fast, while others took a more cautious approach…

Manufacturing the PCB

Now it was up to me to finalise the initial design and get it manufactured.


I choose PCBWay for my PCB manufacturing. Why? What makes them different from the rest?

PCBWay‘s business goal is to be the most professional PCB manufacturer for prototyping and low-volume production work in the world. With more than a decade in the business, they are committed to meeting the needs of their customers from different industries in terms of quality, delivery, cost-effectiveness and any other demanding requests. As one of the most experienced PCB manufacturers and SMT Assemblers in China, they pride themselves to be our (the Makers) best business partners, as well as good friends in every aspect of our PCB manufacturing needs. They strive to make our R&D work easy and hassle-free.

How do they do that?

PCBWay is NOT a broker. That means that they do all manufacturing and assembly themselves, cutting out all the middlemen, and saving us money.

PCBWay’s online quoting system gives a very detailed and accurate picture of all costs upfront, including components and assembly costs. This saves a lot of time and hassle.

PCBWay gives you one-on-one customer support, that answers you in 5 minutes ( from the Website chat ), or by email within a few hours ( from your personal account manager). Issues are really resolved very quickly, not that there are many anyway, but, as we are all human, it is nice to know that when a gremlin rears its head, you have someone to talk to who will do his/her best to resolve your issue as soon as possible.

Find out more here

Conclusion – Part 1

The assembly of the first board was done by myself, and firmware development was started. Stay tuned for Part 2 where the students will get the opportunity to assemble a SMD PCB for the very first time in their lives…

Single Cell Lipo Charger

This single cell lipo charger was created to solve a problem I encountered during a recent project. I constantly needed to recharge 18650 cells, and while I could also use my 4-cell charger, that didn’t always turn out to be the most practical. I also intend to use this small charger as a building block for a future complete power solution, including a boost converter, more protection features and proper cell status indication…

I am currently moving towards building more projects that will be used outside, “in the wild” and thus need a reliable way to power those. True to my way of doing things, I want to build my own stuff as far as possible. That way, I learn more about the technology, and I am sure that everything meets my exact specifications.

What is on the PCB?

The charger is based on the MCP73832T, by Microchip, which contains quite a lot of useful features, in a small package as well at a relatively small price tag, and with very few other required supporting components.

  • Linear Charge Management Controller:
  • Integrated Pass Transistor
  • Integrated Current Sense
  • Reverse Discharge Protection
  • High Accuracy Preset Voltage Regulation: + 0.75%
  • Four Voltage Regulation Options:
  • 4.20V, 4.35V, 4.40V, 4.50V
  • Programmable Charge Current: 15 mA to 500 mA
  • Selectable Preconditioning:
  • 10%, 20%, 40%, or Disable
  • Selectable End-of-Charge Control:
  • 5%, 7.5%, 10%, or 20%
  • Charge Status Output
  • Tri-State Output – MCP73831
  • Open-Drain Output – MCP73832
  • Automatic Power-Down
  • Thermal Regulation
  • Temperature Range: -40°C to +85°C
  • Packaging:
  • 8-Lead, 2 mm x 3 mm DFN
  • 5-Lead, SOT-23

A proper screw-type connection terminal on the output, as well as a DC Barrel Jack on the input, completes the PCB. On future revisions, I will seriously consider having a voltage-limiting circuit on the input side, since the MCP73832T is only capable of accepting an input voltage of up to 5.5v DC.

This is not a problem to me, as I will be using the current version for my own personal use. I do however believe it is essential to ensure that no over-voltage conditions can accidently occur BEFORE I will give this to someone else to use.

The schematic

Manufacturing the PCB

I choose PCBWay for my PCB manufacturing. Why? What makes them different from the rest?

PCBWay‘s business goal is to be the most professional PCB manufacturer for prototyping and low-volume production work in the world. With more than a decade in the business, they are committed to meeting the needs of their customers from different industries in terms of quality, delivery, cost-effectiveness and any other demanding requests. As one of the most experienced PCB manufacturers and SMT Assemblers in China, they pride themselves to be our (the Makers) best business partners, as well as good friends in every aspect of our PCB manufacturing needs. They strive to make our R&D work easy and hassle-free.

How do they do that?

PCBWay is NOT a broker. That means that they do all manufacturing and assembly themselves, cutting out all the middlemen, and saving us money.

PCBWay’s online quoting system gives a very detailed and accurate picture of all costs upfront, including components and assembly costs. This saves a lot of time and hassle.

PCBWay gives you one-on-one customer support, that answers you in 5 minutes ( from the Website chat ), or by email within a few hours ( from your personal account manager). Issues are really resolved very quickly, not that there are many anyway, but, as we are all human, it is nice to know that when a gremlin rears its head, you have someone to talk to who will do his/her best to resolve your issue as soon as possible.

Find out more here

Assembly and Testing

Assembly of this PCB was quite easy, providing that you have a stencil, it will not take you more than a few minutes.


The PCB’s really came out very nicely 🙂


I have also made provision for using a through-hole 18650 battery holder, just in case you are like me, and have a few lying around in a drawer, or could just not be bothered with using the SMD version…


The completed PCB is relatively small and compact, taking into consideration the size of the 18650 cell of course… The screw terminal on the output really helps to keep everything secure when using the module to power a project, and the DC barrel jack provides a good connection to charge it all back up again…
Now, If I just remembered to add some form of voltage limiting on the input, as well as include a boost converter, It would be the perfect little “power bank” project… For now though, let’s leave those features to the future, as this is already extremely useful as is.

MCP23008 Breakout

I designed this breakout to assist me during prototyping my next version of the “RP2040 Emergency Mouse“. In that project, I used the SEEED Studio Xiao RP2040, along with a few other components to create a simple but effective computer mouse-type device.

While the “mouse” works quite well, I have quite early on discovered that it could be better. More on that in a follow-up article, but let us just say that I needed more GPIO pins than that were available on the XIAO RP2040 and that the layout can be improved a bit – especially If I want to get it into an enclosure.

I am still quite neutral about CircuitPython and Micropython on microcontrollers, and Python in general, but since the above-mentioned project runs completely on CircuitPython, it made a lot of good sense to get more into it.

What is on the PCB?


I wanted something as small as possible, and that meant that I chose a QFN package for the MCP23008 IO expander chip. At only 4mm x 4mm, and not being bothered to try and find a DIP version, a breakout board became a much-needed necessity.

Address Selection Jumpers, Two I2C bus headers, and of course the all-important GPIO pins make up all of the user accessible interfacing. Note that the chip reset line is permanently tied to Vcc to make things a bit less cluttered, and easier to use while prototyping.

A decoupling capacitor, as well as pullup resistors on the I2c lines, were also included. Another note here, I did not provide my usual selection jumper to disable these on this particular board.

The Schematic


Manufacturing the PCB

I choose PCBWay for my PCB manufacturing. Why? What makes them different from the rest?

PCBWay‘s business goal is to be the most professional PCB manufacturer for prototyping and low-volume production work in the world. With more than a decade in the business, they are committed to meeting the needs of their customers from different industries in terms of quality, delivery, cost-effectiveness and any other demanding requests. As one of the most experienced PCB manufacturers and SMT Assemblers in China, they pride themselves to be our (the Makers) best business partners, as well as good friends in every aspect of our PCB manufacturing needs. They strive to make our R&D work easy and hassle-free.

How do they do that?

PCBWay is NOT a broker. That means that they do all manufacturing and assembly themselves, cutting out all the middlemen, and saving us money.

PCBWay’s online quoting system gives a very detailed and accurate picture of all costs upfront, including components and assembly costs. This saves a lot of time and hassle.

PCBWay gives you one-on-one customer support, that answers you in 5 minutes ( from the Website chat ), or by email within a few hours ( from your personal account manager). Issues are really resolved very quickly, not that there are many anyway, but, as we are all human, it is nice to know that when a gremlin rears its head, you have someone to talk to that will do his/her best to resolve your issue as soon as possible.

Find out more here

Assembly and Testing

Due to the small size of the QFN package, I strongly recommend that you either have this assembled professionally, or at least consider buying a stencil for applying the solder paste to this board. Maybe those with excellent eyesight can do without that?


Assembly took only a few minutes, with the help of an extremely accurate stencil, followed by a few minutes on a hotplate, and manually soldering on the header pins.

Using the MCP23008 with CircuitPython

I2C devices are very easy to use with the Arduino IDE or similar, and as such, I will not be covering that here.

Circuitpython, however, is gaining popularity, and I am slowly starting to see what the hype is about myself…

So, to get started, you need a microcontroller running CircuitPython – See Adafruit for excellent tutorials. You will also need a few libraries from Adafruit
See this link

I will give a very simple example below, showing how to set a pin as an output, as well as an input with internal pullup resistors enabled. Note that the MCP23008 DOES NOT SUPPORT pull-down resistors internally. You need to add those by yourself externally.

# Initialising all the required libraries
import board
import busio
from digitalio import Direction
from adafruit_mcp230xx.mcp23008 import MCP23008
i2c = busio.I2C(board.SCL, board.SDA)
# Adding the MCP23008
mcp = MCP23008(i2c)
# This assumes that you are using the default address [ i.e. all address 
# pins are grounded]
#
#
#
# Defining two outputs on pins 0 and 1
pin0 = mcp.get_pin(0)
pin0.direction = Direction.OUTPUT
pin1 = mcp.get_pin(1)
pin1.direction = Direction.OUTPUT
#
#
# We can now control the pins by setting them to true or false, true being 
# high
pin0.value = True
pin1.value = True
#
# and switch them off again by using
pin0.value = False
pin1.value = False
#
#
# We can also use the pins as inputs.
# We will activate the internal pullup as well
#
# first , we need another library
import digitalio
pin2 = mcp.get_pin(2)
pin2.direction = digitalio.Direction.INPUT
pin2.pull = digitalio.Pull.UP
#
#
# Reading the pin value is now as easy as 
pin2.value
#
# This will return True if the pin is high ( its default state with pullups # activated, of False if pulled low, by for example a switch of button )

Conclusion

The breakout works as expected, and it is very easy to use with CircuitPython.
I can now continue with the actual integration and Software for the RP2040 Mouse Rev 2.0 project.

High Current P-Mos Driver

This is a modification of my existing P-MOS driver circuits, intended for use with higher current LED Lights, as well as any other applications requiring a higher current capable P-Channel Mosfet to switch a load.

What is on the PCB?

I have used the IRF4905 P-Channe Mosfet here as it can sink up to 74 Amps of current – A complete overkill in many situations. Datasheet. The Mosfet is configured in a high-side switching configuration, thus eliminating problems with ground connections.

To prevent unreliable switching, a transistor is used to switch the gate, which is normally pulled high to keep the device switched off.


I have also included various connection headers for connecting the load, Power supply, as-well-as active high control headers for controlling the driver from a microcontroller. This was especially important as the Gate voltage of the Mosfet is above the acceptable 3.3 volt for use with many of the modern microcontrollers in use today.

It is important o note that I did not yet bother to do very accurate gate current calculations. I do not need super fast switching, and on the bench, the 500mA switching capability of the S9013W transistor gave me satisfactory results.

What is my intended use for this driver?

This is a 12v Automotive Fog light. It is meant to be an aftermarket upgrade. It will also be a very nice focused working light in my workshop, as the lighting is not optimal.

My initial idea is using two of these, PWM controlled from an ESPHome-controlled device to provide me with focused, dimmable lighting for assembly and other operations where a bit of extra light will be needed.

The Fish-eye lens of the internal lamp provides a very focused beam, and from initial testing seems to be exactly what I want.

The problem came in that the LED module consumes quite a bit of current ( 5A for the center lamp, and 3A for the ring light). These currents are way above the capabilities of my existing LED COB driver circuit, thus this MOD.

The Schematic

Manufacturing the PCB

I choose PCBWay for my PCB manufacturing. Why? What makes them different from the rest?

PCBWay‘s business goal is to be the most professional PCB manufacturer for prototyping and low-volume production work in the world. With more than a decade in the business, they are committed to meeting the needs of their customers from different industries in terms of quality, delivery, cost-effectiveness and any other demanding requests. As one of the most experienced PCB manufacturers and SMT Assemblers in China, they pride themselves to be our (the Makers) best business partners, as well as good friends in every aspect of our PCB manufacturing needs. They strive to make our R&D work easy and hassle-free.

How do they do that?

PCBWay is NOT a broker. That means that they do all manufacturing and assembly themselves, cutting out all the middlemen, and saving us money.

PCBWay’s online quoting system gives a very detailed and accurate picture of all costs upfront, including components and assembly costs. This saves a lot of time and hassle.

PCBWay gives you one-on-one customer support, that answers you in 5 minutes ( from the Website chat ), or by email within a few hours ( from your personal account manager). Issues are really resolved very quickly, not that there are many anyway, but, as we are all human, it is nice to know that when a gremlin rears its head, you have someone to talk to that will do his/her best to resolve your issue as soon as possible.

Find out more here

Assembly and Testing

This PCB is definitely quite easy to assemble, as there are only 16 SMD components on the board. These are all easily hand-solderable. The Mosfets and their respective heatsinks are through-hole components and thus super easy as well.

It is very important to note that we should NOT connect the heatsinks together. This is due to the fact that the Heatsink is connected to the DRAIN pin on the MOSFET. Connecting them together will thus short the various channels together.

For my testing procedure, I have connected the driver to the LED Fog light, as well as a 12v supply. Using an ESP8266 running ESPHome, the LED fog light was controlled with PWM. The current draw was 5A and 3A respectively. All of the MOSFETs remained cool to the touch, and the PCB tracks did not heat up as well.

Next steps

The next steps for this project would be to design a PCB that integrates this driver with the ESPHome control device, as well as design and build a suitable enclosure for the two lights and the control unit. This should ideally be mountable on the ceiling above my workbench. It would also be nice to design some sort of gimbal for each light, that can be controlled with stepper motors or servo’s to allow me to position the lights where I need them.

“The Emergency Mouse” – A project born out of necessity

Imagine You are working on a project late on a Friday evening and suddenly your mouse stops working… You can not scroll, and the right-side button won’t respond to your clicks… At the same time, you have a project design that has got to get finished… and the shops are all closed already…

These were the circumstances that led to the birth of “The Emergency Mouse” – A project born out of necessity. How did I solve my problem?

Having access to a lot of electronic modules saved the day. As a maker, I always have various modules and gadgets lying around, and on this unfortunate evening, I remember that the RP2040 has USB HID support. Combine that with a simple Analog Joystick module, a rotary encoder and some push buttons, add about 30 minutes worth of browsing the internet, struggling along with a broken mouse – we have to give the old one credit, it had a very long and hard life, and I finally found some example code that did not just jiggle the mouse pointer or do something equally silly…

The only problem with all of that was that the code was for CircuitPython… I generally dislike using Python on a Microcontroller, as I believe it is better suited for the computer, but, I am warming up to the idea… slowly…

The initial fix – a mess of wires on a breadboard

I quickly grabbed a RaspBerry Pi Pico out of a box, plugged it into a breadboard, loaded Circuitpyth and fired up the example code I got on the internet… While promising, It did not exactly do what I wanted… so a few minutes later, after some coding, I had a moving pointer, controlled by the small thumb joystick module, and with the center button as a “right button”…

So far so good… I can work more easily, but still did not have scrolling… so lets hit the datasheets and documentation on the Adafruit Website (not sponsored) and add a rotary encoder… works well, add more buttons, etc etc…

Eventually it was all done, and about 1 hour has passed, but we were left with a huge ugly mess on a breadboard, and a lot of unused GPIO pins.. So this Pico must go… it can be used for something more useful later…

Then my eye fell on a SEEED Studio XIAO RP2040 module, almost begging to be used… This is smaller, more compact… lets try that …

Initial breadboard version, here shown with the SEEED Studio XIAO RP2040

What functions did this “mouse” have

After changing to the XIAO RP2040, things went very quick…

I added two buttons for scrolling up and down, simulating a mouse wheel,
but kept the encoder… which, while VERY awkward to use at this stage, definitely had potential in the long run…

I also added another button to take over the function of a right button, while the center button on the joystick became left…

Disaster averted, with only about 2 hours wasted, I returned to my project and managed to get it finished using the “improvised-mouse-on-the-breadboard” contraption…

That night, while lying in bed, trying to get to fall asleep, the possibilities of this “contraption-on-the-breadboard” would not let me go… I am fairly old-school, and during the late 80’s and early 90’s owned quite a few “roller-ball” mouse devices… these later became trackballs, and being excessively overpriced, was promptly removed from my environment – the old ones did not last very long, and the new ones were, as I said, overly expensive…

I did however never forget the ease of use that first “rollerball mouse” gave me all that years ago, using only my thumb to move it around etc etc…

This idea would have to be investigated, and turned into a PCB… with that, I finally drifted off to sleep…

The PCB design

The next morning came, and due to reasons unknown, as well as being lazy, I decided not to leave the house, and go buy a new mouse. lets try online… No, they are crazy – I am not paying that for a mouse!

All the time using the “contraption-on-the-breadboard”. So this thing started growing on me… lets design a PCB

The Initial PCB design

After a few hours spent on deciding on optimal layout, I came up with this…
It was still a bit unrefined, but definitely had potential… It lacked a dedicated center button, and those momentary push-buttons requires a lot of force to use… but as a prototype, why not…

Let’s get this manufactured.

For this build, since I used a SEEED Studio module, I decided to send it to SEEED for manufacturing… no need to get components from various places, as they should have all in stock…

Seeed Studio’s Fusion service seamlessly marries convenience with full-feature capabilities in one simple platform. Whether you are prototyping or looking for a mass production partner or based on open source product customization requirements and other design manufacturing services, Seeed Studio Fusion service is catered to your needs starting with a simple online platform. https://www.seeedstudio.com/fusion.html

The PCB arrives from the factory

During the entire time that it took for the PCB to be manufactured and assembled, I was still using this “homemade mouse” – I started calling it a mouse now… and it was still on the breadboard… I never did bother to buy a new mouse, yet..


The PCB Arrived today, and apart from a few small soldering issues, looked great… I still had to do a bit of assembly on my own, as there was an issue with the components I wanted being out of stock.. I have plenty in stock of my own, so opted to do manual assembly…


The completed PCB now only needed a joystick, and some firmware…


After adding a few button caps, and mounting everything to a piece of acrylic plate, I had a working prototype…

The Firmware

As mentioned above, the device runs on CircuitPyton. As Such, there are quite a lot of “examples” on the internet, showing you how to do many USB HID “mouse” like things, but generally being completely useless…

I have thus spent quite a lot of time up to now, writing and refining my own version of the firmware, that is actually useful and does actually work.

It has the following features:
X-Y axis control of the mouse pointer via a thumb joystick, with a left click function on the center joystick button, as well as a dedicated “left” button.

A dedicated “right” button
A “virtual center” button made up of simultaneously pressing left and right

Up and down scrolling either using the rotary encoder as a “mouse wheel” or via dedicated up and down pushbuttons.

A dedicated Reset button – this is necessary, as I can not seem to get the device to initialise correctly at computer bootup.

Various software functions, like changing the pointer acceleration by pressing the center button on the rotary encoder

and most importantly, hiding the Circuitpyton drive, only showing it when I actually need access to the code in this device…

Various statuses are indicated using the NeoPixel on the XIAO, making it easy to see in what state the device is operating.

As such, I shall NOT be releasing the firmware at this moment, as it is still far from being perfect. It works, but it can be way better…

Summary and next steps

Since its “birth” late on a Friday night, about 3 weeks ago, I have been using this device, in its various forms as my primary pointer device. It is growing on me more every day, and it is quite comfortable to use – If we ignore the fact that it is not in a suitable enclosure and that I am still making small changes to the firmware from time to time.

I am already planning the next revision, in which I shall replace the momentary push-buttons with proper microswitches, as well as try my hand at designing a proper enclosure.

If you are a 3D printing expert and want to collaborate with me on this, let’s talk…

Multi-Purpose IO Card

When we are working on a prototype, we always need access to pushbuttons, encoders and even displays to test our ideas in the real world. This Multi-Purpose IO Card was designed to help me do just that…

What is on the PCB?

This PCB was designed with my particular work style in mind. I use a lot of I2C devices, IO Expanders, Displays and sensors. It would thus make sense to have I2C on the PCB, to control an OLED display, as well as a PCF8574 IO expander, that is used to drive a 4×4 Matrix Keypad. Two Rotary encoders, as well as another 4 standard push buttons completes the PCB…

The features, summarised is as follows:

1x Matrix Keypad (4×4) Controlled via an PCF8574 IO expander with selectable addressing.
1x SSD1306 OLED I2C Display
4x Momentary pushbuttons, configured to be used with internal pullups – i.e pushing the button pulls the GPIO LOW
2x Rotary Encoders, with integrated Pushbutton, also configured as Active LOW

The board has all of the connectors and jumpers on the back, making it possible to mount it to an enclosure as a control panel.

I have also provided an additional I2C header to make it possible to add additional devices to the I2C bus easily

The PCB in Detail

PCB Top

Starting from left to right, we have two push-buttons, an OLED display, with two rotary encoders below the display, and another two momentary push buttons. On the Right, we have a 4×4 matrix keypad, and various pin headers for connection to a microcontroller of your choice.

On the back, we have the PCF8574 IO expander for the Matric keypad, addressing Jumpers for the IO expander, as well as the two pin headers for connections to and from a microcontroller…

The Pinouts of these are as follows:
Horizontal 15 pin 2.54mm connector
SDA I2C Data
SCA I2C Clock

GND

SW4 Momentary Push Button 4
SW3 Momentary Push Button 3
SW2 Momentary Push Button 2
SW1 Momentary Push Button 1

RE2-D Rotary Encoder 2 Push Button
RE2-B Rotary Encoder 2 Pin B
RE2-A Rotary Encoder 2 Pin A

RE1-D Rotary Encoder 1 Push Button
RE1-B Rotary Encoder 1 Pin B
RE1-A Rotary Encoder 1 Pin A

GND
VCC 3.3v to 5v DC

The Expansion header extends the I2C Bus, as well as proved access to the interrupt pin on the PCF8574. VCC and GND are also provided.

The Schematic


Manufacturing the PCB

I choose PCBWay for my PCB manufacturing. Why? What makes them different from the rest?

PCBWay‘s business goal is to be the most professional PCB manufacturer for prototyping and low-volume production work in the world. With more than a decade in the business, they are committed to meeting the needs of their customers from different industries in terms of quality, delivery, cost-effectiveness and any other demanding requests. As one of the most experienced PCB manufacturers and SMT Assemblers in China, they pride themselves to be our (the Makers) best business partners, as well as good friends in every aspect of our PCB manufacturing needs. They strive to make our R&D work easy and hassle-free.

How do they do that?

PCBWay is NOT a broker. That means that they do all manufacturing and assembly themselves, cutting out all the middlemen, and saving us money.

PCBWay’s online quoting system gives a very detailed and accurate picture of all costs upfront, including components and assembly costs. This saves a lot of time and hassle.

PCBWay gives you one-on-one customer support, that answers you in 5 minutes ( from the Website chat ), or by email within a few hours ( from your personal account manager). Issues are really resolved very quickly, not that there are many anyway, but, as we are all human, it is nice to know that when a gremlin rears its head, you have someone to talk to that will do his/her best to resolve your issue as soon as possible.

Find out more here

Assembly and Testing

The assembly of this PCB was relatively easy, as it contains only a single SMD component. I do however have to alert you to a certain caveat…

On the PCB, the I2C OLED display pinout is, from left to right,

VCC GND SDC SDA

I have however come across similar displays that swap the GND and VCC pins… and some that even have SCL and SDA swapped…

It is thus quite important that you check your display BEFORE soldering it to this PCB…

Addressing the PCF8574 is also quite easy, with the jumper towards the top is a high, and towards the bottom is a low… They are marked A2 A1 A0 and thus, counting in binary, all low will be 0x20h and all high will be ox27h

Also, note that there are NO I2C Pullup resistors on the board. My microcontroller PCB’s usually have these already, and most I2C Sensors, including the OLED Display that we use, already include as well…
You should thus check what you have on your own hardware, as it is quite impossible to cater for every situation… In a future version, I may add selectable pullup resistors onto this board as well…

Coding and Firmware

The possible uses of this board is quite broad, and the code possibilities are thus also quite extensive. Since I mainly use ESPHome or the Arduino IDE with most of my projects, I wont be including any specialised code here. I think it is enough to say that almost all of the available PCF8574 Matrix Keypad libraries available for the Arduino IDE will fork with this board…

The pinouts are important, and thus :

Row 0 – P0
Row 1 – P1
Row 2 – P2
Row 4 – P3

Col 0 – P7
Col 1 – P6
Col 2 – P5
Col 3 – P4

As far as ESPHome goes, you will need to
1) Add an I2c bus for your device
2)Add a PCF8574 component
3)Add a Matrix Keypad component, and refer the rows and columns to the pins on the PCF8574 – See below for an example of how I have done that in a previous project.

#I2C bus

i2c:

sda: 4

scl: 5

scan: true

id: I2C_Bus

#
# In my case, SDA is on GPIO4 and SCL is on GPIO5
# This is similar to the standard configuration on a NodeMCU v2 Dev board
#

#
# The next step is to configure the actual IO Expander, which in my case is located 
# at address 0x27
#

#PCF8574

pcf8574:

- id: 'pcf8574_hub'

address: 0x27

pcf8575: false


#
# Now we can add the actual keypad interface to the YAML file
# Take note of the difference from the ESP32 file above.
#
#

#KEYPAD

matrix_keypad:

id: mykeypad

rows:

- pin:

pcf8574: pcf8574_hub

# Use pin number 0

number: 0

# In the ESP32 file, we wHereould specify a pin directly like:
#
# -pin: 17
#
# That approach will not work for us.
# The reason for that is that we have to redirect the GPIO to a 
# physical pin on the PCF8574 IO expander.
#
# That is done with the following syntax
#
# - pin:
#pcf8574: pcf8574_hub -- This is the ID of the PCF8574 device -
#number: 0 -- The actual pin number

- pin:

pcf8574: pcf8574_hub

# Use pin number 0

number: 1

- pin:

pcf8574: pcf8574_hub

# Use pin number 0

number: 2

- pin:

pcf8574: pcf8574_hub

# Use pin number 0

number: 3

columns:

- pin:

pcf8574: pcf8574_hub

# Use pin number 0

number: 7

- pin:

pcf8574: pcf8574_hub

# Use pin number 0

number: 6

- pin:

pcf8574: pcf8574_hub

# Use pin number 0

number: 5

- pin:

pcf8574: pcf8574_hub

# Use pin number 0

number: 4

keys: "123A456B789C*0#D"

has_diodes: false

The Rotary encoders and momentary push-buttons can be handled in the same manner, using standard libraries in the Arduino IDE, or a rotary encoder component in ESPHome…

The OLED display would also be handled as above, with a DISPLAY component in ESPHome…

Summary and next steps

The next steps, for me at least, would be to design and CNC cut a suitable enclosure for the IO panel/Control panel in order to make it easier to use…

The panel was designed to be a tool to aid me while designing, and part of my never-ending battle getting rid of breadboards.

It does its job well, at least so far, and works as I have intended it to.