Author: Perry

  • 3D Printed NeoPixel Clock

    This project is for a digital clock based on NeoPixels driven by an Arduino microcontroller. One thing to note is the clock is huge! The dimensions are 43.5cm x 16cm.


    Introduction

    The 3D design is not mine but can be downloaded from thingyverse: 7 Segment IOT Smart Clock

    The original project was based on an IOT clock controlled by an online dashboard. I didn’t need that level of sophistication so I opted to use an Arduino R4 with its internal real time clock (RTC) to keep time. This was not a great idea as it turns out, more of that later.

    The project is not complete but is a working in-progress. For instance, I have not included a way to set the time without using the computer. I also want to add a method to change the colour of the digits and a way to dim the digits in dark ambient light.


    Design

    As already mentioned the 3D design is available on Thingyverse.

    For the electronics I decided to use an Arduino microcontroller as I had experience driving NeoPixels for my model railway layout. A library is used for the NeoPixels and is available from Adafruit.

    My idea was to use the Arduino R4 Nano as it has an internal RTC which can be kept active using a small 3v battery for when power is removed from the clock. This was easy to program and works as expected. That was until I noticed the clock was not very accurate. It was gaining time meaning the clock was out by minutes at the end of the day. It is well documented and not easy to fix. I could automatically reset the time each day to keep it more accurate but in the end I decided to use an external RTC. The RTC of choice was the DS3231 which I got preassembled from eBay.


    Construction

    Start by printing the 3D case. I used Black PLA+ for the surrounds and backs, and I used white PLA+ for the individual segments. Before assembly, I created a paper template of the segments so I could assemble the NeoPixels.

    I stuck the NeoPixels to the template and soldered connections between keeping mind of the flow (NeoPixels have an input and output) connecting the output of one pair of pixels to the input of the next. I labelled the segments using the traditional 7 segment labels, a-g. On the first and last connection I had longer wires with connectors to connect to the next digit.

    The digits need to be screwed together with 3mm screws and nuts. They are hidden inside. The NeoPixel digits can then be glued in place and connected to the next digit. The first digit will have connections for the Arduino and then connect to the second digit through the centre hole.

    At this point I prototyped the Arduino hardware on a plug in breadboard and connected to the NeoPixels assembled in the enclosure.

    Now you can assemble the Arduino on a piece of veroboard with connections for the NeoPixels and a second veroboard with the RTC. I also used a small DC-DC converter to step down the 12v adaptor I had to 5v for the Arduino.

    There should be enough room to connect the Arduino to the computer for programming without removing it. When connecting to the computer I removed the connection to the NeoPixels to avoid drawing too much current from the computer.


    Code

    The code is split in a number of parts. First is the declaration of libraries and global variables.

    /*
    *
    *   Copyright (c) 2026, Perry Andrews 
    *   https://www.pelnet.co.uk
    *   All rights reserved.
    *
    *   Title: NeoPixel Clock
    */
    
    #include <Adafruit_NeoPixel.h>
    #include <Wire.h>
    #include <DS3231-RTC.h>
    
    // Define the NeoPixels Arduino pin  
    #define LED_PIN     6
    
    // How many NeoPixels are attached to the Arduino
    #define LED_COUNT  58
    
    // NeoPixel brightness, 0 (min) to 255 (max)
    #define BRIGHTNESS 128
    
    // Declare our NeoPixel strip object:
    Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB);
    
    DS3231 myRTC;
    
    // Set these values for the RTC
    byte year = 26;
    byte month = 1;
    byte date = 11;
    byte dOW = 1;
    byte hour = 21;
    byte minute = 35;
    byte second = 0;
    byte oldhour = 24;
    byte oldminute = 60;

    The values assigned to the time variables is only used during the first programming. At normal startup after the RTC has been set the values are overwritten by the RTC.

    Next is the setup code:

    void setup() {
      
      // Start the I2C interface
      Wire.begin();
    
      // Set Up DS3231 RTC
      bool mode12 = false; // use 24-hour clock mode
      myRTC.setClockMode(mode12); // uploads 'true' (1) to bit 6 of register 0x02
    
      // Set Time - One off, comment out after first run.
      /*
      myRTC.setYear(year); // uploads 22 to register 0x06
      myRTC.setMonth(month); // uploads 1 to register 0x05
      myRTC.setDate(date); // uploads 5 to register 0x04
      myRTC.setDoW(dOW); // uploads 1 to register 0x03 (Sunday)
      myRTC.setHour(hour); // uploads 19 to register 0x02
      myRTC.setMinute(minute); // uploads 17 to register 0x01
      myRTC.setSecond(second); // uploads 42 to register 0x00
      */
        
      // Initialise LEDR, LEDG and LEDB as outputs
      pinMode(LEDR, OUTPUT);
      pinMode(LEDG, OUTPUT);
      pinMode(LEDB, OUTPUT);
      
      // Turn off all LEDs initially
      digitalWrite(LEDR, HIGH);
      digitalWrite(LEDG, HIGH);
      digitalWrite(LEDB, HIGH);
    
      strip.begin();           // Initialise NeoPixel
      strip.show();            // Turn OFF all pixels ASAP
      strip.setBrightness(BRIGHTNESS); // Set BRIGHTNESS
    
      display_digit(0,0,0);
      
      // Turn on the built-in red LED and turn off the rest
      digitalWrite(LEDR, LOW);
      digitalWrite(LEDG, HIGH);
      digitalWrite(LEDB, HIGH);
      
    }

    The serial interface was used for debugging but I removed from the final code.

    The loop code:

    void loop() {
      // put your main code here, to run repeatedly:
      bool h12;
      bool hPM;
      bool CenturyBit;
      char digitcol = 7; // White Digits
    
      byte date = myRTC.getDate();
      byte month = myRTC.getMonth(CenturyBit);
      byte year = myRTC.getYear();
      byte dOW = myRTC.getDoW();
      byte hour = myRTC.getHour(h12, hPM);  
      byte minute = myRTC.getMinute();
      byte second = myRTC.getSecond();
    
      // Display Time on NeoPixel Display
      if (hour != oldhour){
        oldhour = hour;
        display_digit(hour % 10,2,digitcol);
        hour = hour / 10;
        display_digit(hour,3,digitcol);
        //oldminute = 60;
      }
      if(minute != oldminute){
        oldminute = minute;
        display_digit(minute % 10,0,digitcol);
        minute = minute / 10;
        display_digit(minute,1,digitcol);
        display_colon(digitcol);
      }
    }

    Additionally there are some subroutines called in loop:

    void display_colon(char col){
      uint32_t colour;
      switch(col){
        case 0:
          colour = strip.Color(0, 0, 0);  //Off
          break;
        case 1:
          colour = strip.Color(255, 0, 0);  //Red
          break;
        case 2:
          colour = strip.Color(0, 255, 0);  //Green
          break;
        case 3:
          colour = strip.Color(0, 0, 255);  //Blue
          break;
        case 4:
          colour = strip.Color(255, 255, 0);  //Yellow
          break;
        case 5:
          colour = strip.Color(255, 0, 255);  //Magenta
          break;
        case 6:
          colour = strip.Color(0, 255, 255);  //Cyan
          break;
        case 7:
          colour = strip.Color(255, 255, 255);  //White
          break;
        default:
          colour = strip.Color(0, 0, 0);  //Off
      }
      strip.setPixelColor(28, colour);
      strip.setPixelColor(29, colour);
    }
    
    void display_digit(char num, char digit, char col){
      char offset = 0;
      uint32_t colour;
    
      switch(digit){
        case 0:
          offset = 0;
          break;
        case 1:
          offset = 14;
          break;
        case 2:
          offset = 30;
          break;
        case 3:
          offset = 44;
          break;
        default:
          offset = 0;
          break;
      }
      switch(col){
        case 0:
          colour = strip.Color(0, 0, 0);  //Off
          break;
        case 1:
          colour = strip.Color(255, 0, 0);  //Red
          break;
        case 2:
          colour = strip.Color(0, 255, 0);  //Green
          break;
        case 3:
          colour = strip.Color(0, 0, 255);  //Blue
          break;
        case 4:
          colour = strip.Color(255, 255, 0);  //Yellow
          break;
        case 5:
          colour = strip.Color(255, 0, 255);  //Magenta
          break;
        case 6:
          colour = strip.Color(0, 255, 255);  //Cyan
          break;
        case 7:
          colour = strip.Color(255, 255, 255);  //White
          break;
        default:
          colour = strip.Color(255, 0, 0);  //Red
      }
      switch(num){
        case 0:
          strip.setPixelColor(0 + offset, colour); //a
          strip.setPixelColor(1 + offset, colour); //a
          strip.setPixelColor(2 + offset, colour); //b
          strip.setPixelColor(3 + offset, colour); //b
          strip.setPixelColor(4 + offset, colour); //c
          strip.setPixelColor(5 + offset, colour); //c
          strip.setPixelColor(6 + offset, colour); //d
          strip.setPixelColor(7 + offset, colour); //d
          strip.setPixelColor(8 + offset, colour); //e
          strip.setPixelColor(9 + offset, colour); //e
          strip.setPixelColor(10 + offset, colour); //f
          strip.setPixelColor(11 + offset, colour); //f
          strip.setPixelColor(12 + offset, strip.Color(0, 0, 0)); //g
          strip.setPixelColor(13 + offset, strip.Color(0, 0, 0)); //g
          strip.show();
          break;
        case 1:
          strip.setPixelColor(0 + offset, colour); //a
          strip.setPixelColor(1 + offset, colour); //a
          strip.setPixelColor(2 + offset, colour); //b
          strip.setPixelColor(3 + offset, colour); //b
          strip.setPixelColor(4 + offset, strip.Color(0, 0, 0)); //c
          strip.setPixelColor(5 + offset, strip.Color(0, 0, 0)); //c
          strip.setPixelColor(6 + offset, strip.Color(0, 0, 0)); //d
          strip.setPixelColor(7 + offset, strip.Color(0, 0, 0)); //d
          strip.setPixelColor(8 + offset, strip.Color(0, 0, 0)); //e
          strip.setPixelColor(9 + offset, strip.Color(0, 0, 0)); //e
          strip.setPixelColor(10 + offset, strip.Color(0, 0, 0)); //f
          strip.setPixelColor(11 + offset, strip.Color(0, 0, 0)); //f
          strip.setPixelColor(12 + offset, strip.Color(0, 0, 0)); //g
          strip.setPixelColor(13 + offset, strip.Color(0, 0, 0)); //g
          strip.show();
          break;
        case 2:
          strip.setPixelColor(0 + offset, strip.Color(0, 0, 0)); //a
          strip.setPixelColor(1 + offset, strip.Color(0, 0, 0)); //a
          strip.setPixelColor(2 + offset, colour);  //b
          strip.setPixelColor(3 + offset, colour);  //b
          strip.setPixelColor(4 + offset, colour);  //c
          strip.setPixelColor(5 + offset, colour);  //c
          strip.setPixelColor(6 + offset, strip.Color(0, 0, 0));  //d
          strip.setPixelColor(7 + offset, strip.Color(0, 0, 0));  //d
          strip.setPixelColor(8 + offset, colour);  //e
          strip.setPixelColor(9 + offset, colour);  //e
          strip.setPixelColor(10 + offset, colour); //f
          strip.setPixelColor(11 + offset, colour); //f
          strip.setPixelColor(12 + offset, colour); //g
          strip.setPixelColor(13 + offset, colour); //g
          strip.show();
          break;
        case 3:
          strip.setPixelColor(0 + offset, colour);  //a
          strip.setPixelColor(1 + offset, colour);  //a
          strip.setPixelColor(2 + offset, colour);  //b
          strip.setPixelColor(3 + offset, colour);  //b
          strip.setPixelColor(4 + offset, colour);  //c
          strip.setPixelColor(5 + offset, colour);  //c
          strip.setPixelColor(6 + offset, strip.Color(0, 0, 0));  //d
          strip.setPixelColor(7 + offset, strip.Color(0, 0, 0));  //d
          strip.setPixelColor(8 + offset, strip.Color(0, 0, 0));  //e
          strip.setPixelColor(9 + offset, strip.Color(0, 0, 0));  //e
          strip.setPixelColor(10 + offset, colour);  //f
          strip.setPixelColor(11 + offset, colour);  //f
          strip.setPixelColor(12 + offset, colour);  //g
          strip.setPixelColor(13 + offset, colour);  //g
          strip.show();
          break;
        case 4:
          strip.setPixelColor(0 + offset, colour);   //a
          strip.setPixelColor(1 + offset, colour);   //a
          strip.setPixelColor(2 + offset, colour);   //b
          strip.setPixelColor(3 + offset, colour);   //b
          strip.setPixelColor(4 + offset, strip.Color(0, 0, 0));  //c
          strip.setPixelColor(5 + offset, strip.Color(0, 0, 0));  //c
          strip.setPixelColor(6 + offset, colour);   //d
          strip.setPixelColor(7 + offset, colour);   //d
          strip.setPixelColor(8 + offset, strip.Color(0, 0, 0));  //e
          strip.setPixelColor(9 + offset, strip.Color(0, 0, 0));  //e
          strip.setPixelColor(10 + offset, strip.Color(0, 0, 0));  //f
          strip.setPixelColor(11 + offset, strip.Color(0, 0, 0));  //f
          strip.setPixelColor(12 + offset, colour);  //g
          strip.setPixelColor(13 + offset, colour);  //g
          strip.show();
          break;
        case 5:
          strip.setPixelColor(0 + offset, colour);   //a
          strip.setPixelColor(1 + offset, colour);   //a
          strip.setPixelColor(2 + offset, strip.Color(0, 0, 0));  //b
          strip.setPixelColor(3 + offset, strip.Color(0, 0, 0));  //b
          strip.setPixelColor(4 + offset, colour);   //c
          strip.setPixelColor(5 + offset, colour);   //c
          strip.setPixelColor(6 + offset, colour);   //d
          strip.setPixelColor(7 + offset, colour);   //d
          strip.setPixelColor(8 + offset, strip.Color(0, 0, 0));  //e
          strip.setPixelColor(9 + offset, strip.Color(0, 0, 0));  //e
          strip.setPixelColor(10 + offset, colour);  //f
          strip.setPixelColor(11 + offset, colour);  //f
          strip.setPixelColor(12 + offset, colour);  //g
          strip.setPixelColor(13 + offset, colour);  //g
          strip.show();
          break;
        case 6:
          strip.setPixelColor(0 + offset, colour);   //a
          strip.setPixelColor(1 + offset, colour);   //a
          strip.setPixelColor(2 + offset, strip.Color(0, 0, 0));  //b
          strip.setPixelColor(3 + offset, strip.Color(0, 0, 0));  //b
          strip.setPixelColor(4 + offset, colour);   //c
          strip.setPixelColor(5 + offset, colour);   //c
          strip.setPixelColor(6 + offset, colour);   //d
          strip.setPixelColor(7 + offset, colour);   //d
          strip.setPixelColor(8 + offset, colour);   //e
          strip.setPixelColor(9 + offset, colour);   //e
          strip.setPixelColor(10 + offset, colour);  //f
          strip.setPixelColor(11 + offset, colour);  //f
          strip.setPixelColor(12 + offset, colour);  //g
          strip.setPixelColor(13 + offset, colour);  //g
          strip.show();
          break;
        case 7:
          strip.setPixelColor(0 + offset, colour);   //a
          strip.setPixelColor(1 + offset, colour);   //a
          strip.setPixelColor(2 + offset, colour);   //b
          strip.setPixelColor(3 + offset, colour);   //b
          strip.setPixelColor(4 + offset, colour);   //c
          strip.setPixelColor(5 + offset, colour);   //c
          strip.setPixelColor(6 + offset, strip.Color(0, 0, 0));  //d
          strip.setPixelColor(7 + offset, strip.Color(0, 0, 0));  //d
          strip.setPixelColor(8 + offset, strip.Color(0, 0, 0));  //e
          strip.setPixelColor(9 + offset, strip.Color(0, 0, 0));  //e
          strip.setPixelColor(10 + offset, strip.Color(0, 0, 0));  //f
          strip.setPixelColor(11 + offset, strip.Color(0, 0, 0));  //f
          strip.setPixelColor(12 + offset, strip.Color(0, 0, 0));  //g
          strip.setPixelColor(13 + offset, strip.Color(0, 0, 0));  //g
          strip.show();
          break;
        case 8:
          strip.setPixelColor(0 + offset, colour);   //a
          strip.setPixelColor(1 + offset, colour);   //a
          strip.setPixelColor(2 + offset, colour);   //b
          strip.setPixelColor(3 + offset, colour);   //b
          strip.setPixelColor(4 + offset, colour);   //c
          strip.setPixelColor(5 + offset, colour);   //c
          strip.setPixelColor(6 + offset, colour);   //d
          strip.setPixelColor(7 + offset, colour);   //d
          strip.setPixelColor(8 + offset, colour);   //e
          strip.setPixelColor(9 + offset, colour);   //e
          strip.setPixelColor(10 + offset, colour);  //f
          strip.setPixelColor(11 + offset, colour);  //f
          strip.setPixelColor(12 + offset, colour);  //g
          strip.setPixelColor(13 + offset, colour);  //g
          strip.show();
          break;
        case 9:
          strip.setPixelColor(0 + offset, colour);   //a
          strip.setPixelColor(1 + offset, colour);   //a
          strip.setPixelColor(2 + offset, colour);   //b
          strip.setPixelColor(3 + offset, colour);   //b
          strip.setPixelColor(4 + offset, colour);   //c
          strip.setPixelColor(5 + offset, colour);   //c
          strip.setPixelColor(6 + offset, colour);   //d
          strip.setPixelColor(7 + offset, colour);   //d
          strip.setPixelColor(8 + offset, strip.Color(0, 0, 0));  //e
          strip.setPixelColor(9 + offset, strip.Color(0, 0, 0));  //e
          strip.setPixelColor(10 + offset, colour);  //f
          strip.setPixelColor(11 + offset, colour);  //f
          strip.setPixelColor(12 + offset, colour);  //g
          strip.setPixelColor(13 + offset, colour);  //g
          strip.show();
          break;
      }
    }

    This is all the code used. I appreciate there is probably a better way to implement displaying a digit.


    Conclusion

    This is a first iteration of the project and is not complete. Also, I have not optimised the code in any way and so there could be bugs and inefficiencies in the code. However, it does work.

    The following improvements will be implemented at a future date.

    • Light sensor to dim the brightness in dark ambient light
    • Buttons to set the time without using the computer
    • Button to change digit colours
    • Alternative IR remote control to set time & colour

    I hope this project has been inspirational and shows you can create a project based on someone else’s shared work.


    Links

    7 Segment IOT Smart Clock

    Adafruit NeoPixel Library

    Arduino R4 Nano Manual

  • Happy 2026!

    Happy new year!

    Let’s hope 2026 brings good health, peace and good fortune.

    Some projects I am working on are a large digital clock based on a design shared on Thingiverse, CAN bus model railway control using Arduino Nano R4 and documenting some of my older projects and binging them up to date.

    I hope you enjoy!

  • 2025 Favourite Photos

    These are some of my favourite photos from 2025.


  • 8 Bit Computing

    8 Bit Computing

    8 Bit Computing, a trip down memory lane.

    While still at school back in the 1980’s, home computers started becoming available and I was fortunate enough to be loaned a ZX80 by a friend. This started my passion for computers and programming. It also allowed me to experiment with interfacing computers with electronics projects.

    This is not an extensive guide to 8 bit computers but a trip down memory lane describing the computers I have owned over the years, most of which I still have.

    Sinclair ZX80

    Released: 1980
    CPU: Z80

    My ZX80 was loaned to me and had a little pink plastic box on top that contained a circuit to convert it to a ZX81. This circuit in combination with a new ROM allowed ZX81 software to to run on it and removed the annoying pause in display when the computer was doing something.

    The photograph here was taken at the Centre for Computing History in Cambridge.

    Sinclair ZX81

    Released: 1981
    CPU: Z80

    My original ZX81 suffered from a keyboard failure and I created a makeshift keyboard from PCB switches. I had the original case without the keyboard and purchased two more from eBay over the years including a boxed version.

    After a recent test I had to use components from each to provide a single working version. It is difficult to get a usable picture from a ZX81 on a modern LCD television or monitor so a modification is required to provide the correct composite signal these monitors need.

    I used a simple version to test my ZX81 but I need to build a better version for a good display.

    Acorn BBC Micro

    Released: 1981
    CPU: 6502

    I have a BBC Micro Model B in my collection that was given to me by a friend. It had been heavily modified with extra memory and additional ROM space. I removed these and returned it back to as standard a condition as possible.

    I have a dual 51/4″ disk drive for it and more recently I purchased a SD Card Drive. A while ago it suffered from the dreaded breakdown of the power supply capacitors resulting in a lot of smoke.

    I replaced the capacitors and the computer sprang back to life.

    Sinclair ZX Spectrum

    Released: 1982
    CPU: Z80A

    I have a 48K Spectrum I purchased from eBay many years ago. I only checked it worked and never did much more with it. At some point I will set it up and take some pictures.

    Dragon Data Dragon 32

    Released: 1982
    CPU: 6809

    I have two Dragon 32’s in my collection and a Dragon 64. My original Dragon 32 was removed from its case and put in a home made case. Many years later after my original case disappeared, I bought a non-working Dragon from eBay and restored it to a working condition using my original PCB’s

    Later a second Dragon was given to me by a friend along with a collection of software titles most of which I have now. Back in the 1980’s I really wanted a Dragon 64 and over 30 years later I added one to my collection.

    This is my favourite 8 bit computer and is the one I use the most now.

    Apple IIe

    Released: 1983
    CPU: 6502

    My Apple IIe belonged to my father-in-law. I have not used it much but I still have the disk drives and software he originally purchased.

    This is the end of my trip down memory lane. There is quite a revival of 8 bit home computing and lots of Facebook groups exist for like minded people.

    My next memory of home computing will be about the 16 bit era.


    Links

  • My Webcam

    Introduction

    For many years I had a webcam on my website and have used different methods of making it work. It mainly consisted of a PC or Linux Computer and a USB Camera. This was overkill for a webcam, being noisy, using more power than necessary and taking up a lot of space.

    When the Raspberry Pi Camera was launched I could see an immediate use to create a webcam that would overcome all of the downfalls of my current set-up. I had already been using the Raspberry Pi so adding a camera was not too much effort.

    My first Webcam used the original Raspberry Pi Model B. I used Raspian and created a script to take pictures every 5 minutes. The script also uploaded them to my website. This was scheduled using cron.


    Design

    My latest Webcam is a Raspberry Pi 3 Model B computer with a camera and is stuck to a window with the camera pointing outside. Every 5 minutes it takes a photo with the camera and uploads it to my website. You can see the webcam in action here.

    I use is Raspberry Pi OS and the webcam software is picam which can be downloaded and installed from the OS. Instructions are provided in the GitHub repository.

    picam can be set up and used in a few different ways. I configured mine to take a picture and upload it to my website. Additionally I enabled the video output so I could record the live footage as a security camera. Using software such as Synology Surveillance Station you can detect motion and record video.

    I also added a RGB LED as a status indicator as when running the webcam is not connected to a monitor.


    Parts

    You will need the following parts for this project:

    • Raspberry Pi 3 Model B
    • Raspberry Pi Camera Module
    • MicroSD Card (16GB)
    • LM2596 DC-DC Step Down Buck Convertor (eBay)
    • 5MM RGB LED
    • 3D Printed Case
    • 20mm Round Button Suction Cup x 4
    • 2.5mm Power Socket
    • 12v 2A PSU with 2.5mm power plug

    You also need wire and connectors for internal connections. I suggest dupont wires which can be cut and soldered on to the LED’s and Buck Convertor and the other end plugged onto the Raspberry Pi Header.

    Everything is available on eBay and considering the current price of later models of Raspberry Pi opt for a used RPi 3 Model B. This has built in wireless so you don’t need to connect to a wired LAN.


    Set-up

    Most of the setup can be done before mounting the Raspberry Pi in a case. You can power the Raspberry Pi using the USB connector and plug the Monitor into the HDMI or Composite connector. You also need a USB keyboard.
    Set up involves downloading Raspberry PI OS from the Raspberry Pi Website and copying it to the microSD card.

    Once copied you need to connect the Raspberry Pi to a monitor, keyboard and power supply. Apply power and let the OS boot to the command prompt.

    From the command prompt you can use the instructions provided on the picam GitHub repository to prepare the OS, download the picam binary and install it.


    Construction

    Print the case using a 3D printer. The case is in two parts. The base is printed using Black PTEG filament. This is less likely to warp when exposed to heat than PLA+. The top cover is printed in any colour PLA+.

    Glue in the camera board with the camera through the square hole. Feed the camera ribbon cable through the thin slot so the cable comes outside the case. Screw in the buck converter and glue in the power socket in it’s small slot.

    Before using the step-down buck converter you need to connect it to the power supply and set the output voltage to 5v. Failure to do this before connecting the Raspberry Pi could be disastrous.

    Fit the Raspberry Pi in the case by angling the ports in the holes first and then pushing the PCB flat. Secure with 4 self tapping screws. Don’t over tighten. Insert the memory card in the slot after the board has been fitted otherwise the PCB is difficult to push flat.

    Connect the Power wires, the Camera ribbon cable and finally the RGB LED wires.

    Use the picture above to connect the wires. The camera ribbon camera can be folded gently to fit under the lid when it is fitted. Be careful not to trap it.

    The lid is fastened with 4 x 3mm screws. Slide the 20mm suction cups into the slots and you are ready to go.


    Links

  • Model Railway LED Dimmer

    In this post I describe a circuit for a Model Railway LED Dimmer. This is used to dim the LED lampposts I am adding to our model railway layout.

    The lampposts on our model railway layout are a bit too bright. There are 1K resistors included and these could be swapped for a higher value to reduce the brightness. Instead, I decided to make a circuit to vary the brightness. This allows the adjustment of brightness after the lampposts are installed. This can be fine tuned when the layout is in night mode.

    LED Dimmer Circuit

    A NPN transistor is used with R1 and RV1 to vary the voltage to the LED’s. The transistor can handle currents up to 800mA so could be used for multiple LED’s. I am dimming 3 lamppost LED’s.

    Assembled LED Dimmer

    The circuit was assembled on Vero board as it is quick to work with and is stable. The wires from the lampposts will be soldered directly onto the Vero board tracks.

    All components can be obtained from Rapid Electronics. The lampposts we are using are these from Layouts4U.

  • 2024 Favourite photos

    These are some of my favourite photos from 2024


  • 6809 Single Board Computer

    6809 Single Board Computer

    Introduction

    This page describes a project to build my own single board computer based on the Motorola 6809 CPU.

    My project is my own version of a design based on information shared by Grant Searle and Jeff Tranter. Without them sharing their projects I would not have been able to create this project. See the links to their pages in the links section below.

    The goal of my project is to have a working single board computer I can use to learn 6809 machine code and to build expansion boards to interface to the outside world.

    Prototype

    The Motorola 6809 CPU was used in a few home computers of the 1980’s era and was an advanced 8-bit CPU at that time. My home computer fascination really took off when I bought my Dragon 32 and although I started to learn machine language at the time I have forgotten most of it now.

    In Development

    When I saw that people had already built simple computers of their own using this older technology I wanted to do the same. I used the original design and purchased the required IC’s from Ebay.

    I created a prototype using solder-less breadboard I bought from Maplin’s closing down sale. It is really helpful to use printed pinouts stuck to the surface of the 4 large IC’s. I used yellow wire for the address bus, blue wires for the data bus and white wires for the control signals such as the E timing signal and R/W line. Red and black wires were also used for the power lines.

    Prototype

    For the basic ROM, I downloaded the one created by Grant Searle and programmed an eprom using a cheapish eprom programmer I bought from Amazon. Although used to programming flash on PIC microcontrollers, I had never programmed an eprom. It took me a while to realise I had to use some offsets when loading the file to make sure the code was at the correct start point in the eprom. The eprom is addressed from C000-FFFF but basic starts from address DB00. The last two bytes of the eprom FFFE and FFFF are the reset vectors and hold the address where program execution should start after a reset (or when first powered on).

    Initial Testing

    I connected the serial connections from the 80B50 IC to a laptop PC using a USB converter and used Putty as the serial terminal program. At first I could not get it to work so I removed the IC’s except the CPU and wired the data bus to the NOP (no operation) instruction to test the CPU. I connected the address bus to a Picoscope MSO to see that when powered on the address bus incremented. The CPU increments the address bus one address at a time from 0000-FFFF. It does it so fast you cannot see it using LED’s. After confirming the CPU was working I rechecked all the connections and plugged the IC’s back in. I connected the Picoscope to the data bus and powered on. I could see the prompt in the serial terminal. Success!

    However, I soon realised that when disconnecting the Picoscope from the data bus it stopped working again. I resolved this by using a 2K2 pull-up resister network on the data bus. I was able to enter a basic program and run it using the serial terminal to see the results. One Issue I saw was after running the program I had no response from the command line. I hit reset and it was ok again (and the basic program was still in memory). It was time to move on and create a PCB which could resolve these issues.

    Construction

    I had already transferred the schematic to Eagle CAD to help me with building the prototype. The pull-up resister network was added to the design after my experience with the prototype. Knowing that if it was still required I had a place for it on the PCB. The layout of my PCB was based on Jeff Tranters design but I modified it. The reset button and the power LED were placed together on the left hand side. I also added room for my USB-Serial converter.

    My 6809 Single Board Computer

    I ordered my PCB’s from All PCB in China who I have been using for a few years now. After about 5 days the PCB’s were here ready for assembly. Great service!
    I started with the IC sockets, then the capacitors, diode and resisters. I wanted to try without the resistor network first to see if it was required or not. Then I added the crystal, LED and reset button. Finally I added the connector pins and socketed the IC’s.

    Final Test

    To test, I connected the USB-Serial converter using Dupoint wire. Final fitting would require me to remove the already soldered on right angle connector from the converter PCB. On power up I did not see the prompt on the serial terminal window. To fix this, I added the pull-up resister network as I did for the prototype. A second test worked! I am not sure why the original designs did not require the pull up of the data bus, but mine does! However I still had the issue with lock up after a program was run. I decided to try the basic as modified by Jeff Tranter as I noticed he had corrected a small bug. Using this newly programmed eprom the lock up issue disappeared. Now everything is working well. Finally I mounted the USB-Serial converter on the PCB.

  • My First Blog Post

    London Night Scene

    Twenty five years on from my first website on my registered domain, www.pelnet.co.uk, I decided to redesign the site to be less reliant on software installed on a computer and be editable using any browser on any type of device.

    This was partly due to cost, I don’t like subscriptions especially for software I use infrequently, but also due to flexibility. I want to create content for my website wherever I am and not wait until I’m home. My site had become static because of this.