Friday, March 31, 2023

0000 0000 1100 0011

The Dirty Dozen - Part Three - curious HC-SR04 module

Out of the box this week comes an "intermediary" module - it hooks up to the HC-SR04 ultrasonic range finder module, displays the distance in cm, and can then output serial data via UART.

The blurb on the module claims that it is STM8S103 based, but the actual chip is a Nuvoton N76E003AT20, which is pretty obscure but the website gives the following:

N76E003 – a 1T-8051 based series MCU, offers 18 KB Flash ROM, configurable Data Flash and 1 KB SRAM. It supports wide operating voltage of 2.4V to 5.5V, temperature range of -40℃ to 105℃, and high noise immunity of 7KV ESD and 4KV EFT.


The chip needs a special programmer if you'd like to chat to it, but even if you could get to it (i.e. de-solder and find a suitable cradle), I'm really not sure how you would alter the code etc to be a bit friendlier - so that's not likely to happen.

As a result of this weirdness I did the obvious and looked at the serial output. It seems that every half second or so it outputted the following wacky string - "D: XXX\R\N". I'm assuming "D" is distance?

I had to cleave off the XXX (representing the actual distance) using the substring() function, and then convert the result to a number.

It worked, but boy is it clunky!

Here is the complete code which outputs to a coloured 10-segment LED module to visually aid distance indication.

// From https://www.programmingelectronics.com/serial-read/
// by Michael James, also
// many thanks to Nick Gammon for the basis of this code
// http://www.gammon.com.au/serial

const unsigned int MAX_MESSAGE_LENGTH = 12;
String convert;
int distance;
void setup() {
  Serial.begin(9600);
  DDRC = B00011111;
  DDRD = B11111000;
}

void loop() {

  //Check to see if anything is available in the serial receive buffer
  while (Serial.available() > 0)
  {
    //Create a place to hold the incoming message
    static char message[MAX_MESSAGE_LENGTH];
    static unsigned int message_pos = 0;

    //Read the next available byte in the serial receive buffer
    char inByte = Serial.read();

    //Message coming in (check not terminating character) and guard for over message size
    if ( inByte != '\n' && (message_pos < MAX_MESSAGE_LENGTH - 1) )
    {
      //Add the incoming byte to our message
      message[message_pos] = inByte;
      message_pos++;
    }
    //Full message received...
    else
    {
      //Print the message (or do other things)
      convert = (String)message;
      convert = convert.substring(2, 5);
      distance = convert.toInt();

      if (distance > 27) {
        PORTC = B00000001;
        PORTD = B00000000;
      }
      else if (distance > 24) {
        PORTC = B00000011;
        PORTD = B00000000;
      }
      else if (distance > 21) {
        PORTC = B00000111;
        PORTD = B00000000;
      }
      else if (distance > 18) {
        PORTC = B00001111;
        PORTD = B00000000;
      }
      else if (distance > 15) {
        PORTC = B00011111;
        PORTD = B00000000;
      }
      else if (distance > 12) {
        PORTC = B00011111;
        PORTD = B10000000;
      }
      else if (distance > 9) {
        PORTC = B00011111;
        PORTD = B11000000;
      }
      else if (distance > 6) {
        PORTC = B00011111;
        PORTD = B11100000;
      }
      else if (distance > 3) {
        PORTC = B00011111;
        PORTD = B11110000;
      }
      else if (distance > 0) {
        PORTC = B00011111;
        PORTD = B11111000;
      }

      //Reset for the next message
      message_pos = 0;
    }
  }
}

I really want to use this module combo on a robot car to do some auto-parking!

If you like the idea, leave a comment on here or in the comments section of the video below.

Enjoy the Dirty Dozen Part III.




 

Friday, March 24, 2023

0000 0000 1100 0010

555 Charge Pump Circuit (noisy PCB)

Recently I made up a 555 square wave generator using a kit that I dug out of the Dirty Dozen box. I thought I would take another at this PCB because I ran out of time to both troubleshoot the circuit and also to use it as I intended in a voltage doubler charge pump circuit.

The trouble shooting was made easy when a viewer suggested to check the power supply. Sure enough I was using a commercial direct buck/boost converter, which of course provided a pretty "bumpy" 12V.

Once I ran the source through an LM338 voltage regulator, and added a couple of smoothing capacitors, the 555 signal cleared up nicely.

Now with the signal sorted I whipped up a quick voltage doubler circuit according to one of the many versions available online, which worked a treat!

Here is the resultant video - enjoy!



Friday, March 17, 2023

0000 0000 1100 0001

The Dirty Dozen - Part Two - RPi Clone

This week I pulled out of the Dirty Dozen box a very cool RPi PICO clone.

To set myself a bit of a task I decided to program in MicroPython using Thonny, not the usual C via the Arduino IDE.

I had seen online some scuttlebutt about the ADC on these things being a little tricky, so I decided to test it out using an LDR which would then affect the integrated WS2812 LED to display light levels.

My Python skills were a little rusty, but after borrowing heavily from the internet, I was able to code the following.

import array, time
from machine import Pin
import rp2
 
# Configure the number of WS2812 LEDs, pins and brightness.
NUM_LEDS = 1
PIN_NUM = 23
brightness = 0.1

ldr = machine.ADC(27)
lightled = 0

BLACK = (0, 0, 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)
WHITE = (255, 255, 255)
COLORS = (WHITE, CYAN, YELLOW, GREEN, PURPLE, RED, BLUE, BLACK)

@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
def ws2812():
    T1 = 2
    T2 = 5
    T3 = 3
    wrap_target()
    label("bitloop")
    out(x, 1)               .side(0)    [T3 - 1]
    jmp(not_x, "do_zero")   .side(1)    [T1 - 1]
    jmp("bitloop")          .side(1)    [T2 - 1]
    label("do_zero")
    nop()                   .side(0)    [T2 - 1]
    wrap()
 
# Create the StateMachine with the ws2812 program, outputting on Pin(16).
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM))
 
# Start the StateMachine, it will wait for data on its FIFO.
sm.active(1)
 
# Display a pattern on the LEDs via an array of LED RGB values.
ar = array.array("I", [0 for _ in range(NUM_LEDS)])
 
def pixels_show():
    dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)])
    for i,c in enumerate(ar):
        r = int(((c >> 8) & 0xFF) * brightness)
        g = int(((c >> 16) & 0xFF) * brightness)
        b = int((c & 0xFF) * brightness)
        dimmer_ar[i] = (g<<16) + (r<<8) + b
    sm.put(dimmer_ar, 8)
    time.sleep_ms(10)
 
def pixels_set(i, color):
    ar[i] = (color[1]<<16) + (color[0]<<8) + color[2]
 
def pixels_fill(color):
    for i in range(len(ar)):
        pixels_set(i, color)
    
for color in COLORS:
    pixels_fill(color)
    pixels_show()
    time.sleep(1.5)
    
while True:
     lightled = ldr.read_u16()
     print(lightled)

     if lightled > 25000:
         pixels_fill(WHITE)
     elif lightled > 24000:
        pixels_fill(CYAN)
     elif lightled > 21000:
        pixels_fill(YELLOW)
     elif lightled > 18000:
        pixels_fill(GREEN)
     elif lightled > 15000:
        pixels_fill(PURPLE)
     elif lightled > 12000:
        pixels_fill(RED)
     elif lightled > 9000:
        pixels_fill(BLUE)
     elif lightled > 6000:
        pixels_fill(BLACK)

     pixels_show()
     time.sleep(0.2)

Loading up into the module was a breeze, and the second instalment of the Dirty Dozen was a success.



 

Friday, March 10, 2023

0000 0000 1100 0000

The Dirty Dozen - Part One - 555 kit

A few months ago in a late night frenzy I bought 12 items from the same supplier. Sick of opening parcels and promising on camera to do something with the package inside, I've made a commitment with this series to use the item straight away.

This week the random selection was a curious 555 kit which was so familiar to me as I had made a very similar project a couple of years ago.

Here it is in a build that took a little longer than expected!





Thursday, March 2, 2023

0000 0000 1011 1111

Update on the Advert Dropper (Orange Pi-hole)

I unashamedly love my Orange Pi-hole. Adverts are dropped, speed is increased and I can see and monitor the activity on the network, PLUS it has a really cool interface!



In a recent mailbag video when another Orange Pi arrived I asked via YT if anyone would be interested in how I maintain and update the device. YT spoke back!

In response to that request I have now made a video of what I do for regular maintenance. It's pretty simple and goes something like this:

1. ssh into the device using "ssh root@192.169.X.X" where XX is the local address

2. apt update

3. apt upgrade

4. pihole -up

That's it! There are quite a few other things that you can do from the console while we're here:

Usage: pihole [options]
Example: 'pihole -w -h'
Add '-h' after specific commands for more information on usage

Whitelist/Blacklist Options:
  -w, whitelist       Whitelist domain(s)
  -b, blacklist       Blacklist domain(s)
  -wild, wildcard     Blacklist domain(s), and all its subdomains
                        Add '-h' for more info on whitelist/blacklist usage

Debugging Options:
  -d, debug           Start a debugging session
                        Add '-a' to enable automated debugging
  -f, flush           Flush the Pi-hole log
  -r, reconfigure     Reconfigure or Repair Pi-hole subsystems
  -t, tail            View the live output of the Pi-hole log

Options:
  -a, admin           Admin Console options
                        Add '-h' for more info on admin console usage
  -c, chronometer     Calculates stats and displays to an LCD
                        Add '-h' for more info on chronometer usage
  -g, updateGravity   Update the list of ad-serving domains
  -h, --help, help    Show this help dialog
  -l, logging         Specify whether the Pi-hole log should be used
                        Add '-h' for more info on logging usage
  -q, query           Query the adlists for a specified domain
                        Add '-h' for more info on query usage
  -up, updatePihole   Update Pi-hole subsystems
  -v, version         Show installed versions of Pi-hole, Admin Console & FTL
                        Add '-h' for more info on version usage
  uninstall           Uninstall Pi-hole from your system
  status              Display the running status of Pi-hole subsystems
  enable              Enable Pi-hole subsystems
  disable             Disable Pi-hole subsystems
                        Add '-h' for more info on disable usage
  restartdns          Restart Pi-hole subsystems
  checkout            Switch Pi-hole subsystems to a different Github branch
                        Add '-h' for more info on checkout usage

-a Usage
Usage: pihole -a [options]
Example: pihole -a -p password
Set options for the Admin Console

Options:
  -p, password        Set Admin Console password
  -c, celsius         Set Celsius as preferred temperature unit
  -f, fahrenheit      Set Fahrenheit as preferred temperature unit
  -k, kelvin          Set Kelvin as preferred temperature unit
  -r, hostrecord      Add a name to the DNS associated to an IPv4/IPv6 address
  -e, email           Set an administrative contact address for the Block Page
  -h, --help          Show this help dialog
  -i, interface       Specify dnsmasq's interface listening behavior
                        Add '-h' for more info on interface usage

To be honest however I only use the graphical interface on the system via a browser. The system works great - highly recommended!

To find out more about this project (and donate if you use it) click on this link.