Brendan 'nog3' Halliday's Picture

Brendan 'nog3' Halliday

Brisbane, Australia 5 posts
WS2812B Circular LED Segment

WS2812B Circular LED Segment

For a while now I've wanted some circular segmented displays for showing countdowns and the like, but didn't want to have to make casings for the $4-5 ws2812 pcb rings. So following in the foot-steps of some edge lit number displays running via ws2812 stirip put on its side, I laser cut a casing.

This is the strip in its natural form -

First I went for a 12 segment display, made out of layers of 6mm clear acrylic for the lights and 3mm black for the housing. Buuut I got the maths wrong and the inner circle was completely the wrong.size.

Still, I was undeterred and dusted off some 10mmish black and some 10mm clear acrylic offcuts I had. I re-did the design and tested it in 6mm acrylic, it was a perfect fit!

So then I upscaled to 10mm and uh, this happened.

All the nice coherent tolerances I'd had in the 6mm were blown away by the increased power needed to cut through the 10mm, everything was about half a millimeter off or so.

So I threw my hands up in the air and tested it anyhow:

Even without the leds touching perfectly, it still worked a treat. I plan on tuesday to cut some bigger clear bits to see if that'll fix the problem.

Aside from that, I'm eyeing up an easier to make version using a single sheet of clear 6mm acrylic using a different width of led strip (sk6812mini).

How to remove Particle from your Digispark Oak ESP8266

How to remove Particle from your Digispark Oak ESP8266

So a while back I backed the Digistump Oak Kickstarter. I thought these boards were great and I'd supported other Digistump projects by backing or purchasing Erik's dev boards.

One of the big drawcards was over the air updates via Particle and at the time the ESP8266 Arduino Core didn't have great OTA support so this was win-win. (It's now waaaay better.)

Now the boards are great and the Oak support for arduino and the firmware was solid. The one thing I never found consistantly solid however was the Particle OTA support. I'd be able to flash it successfully a few times, come back a few months later and then flashing would just randomly and annoyingly fail.

Each time it failed I'd spend days troubleshooting, manually wiping the firmware/bootloader and replacing it until it kinda worked. The Oaks would phone home properly to Particle and show up on the Dashboard but would either stop recieving data during a flash or just stop responding.

Eventually when I came back to work on a project I'd built on the Oak pinout I finally gave in as I spent all the time I'd intended to use for development on fault finding the Particle OTA.

At its core, the Oak is simply an ESP8266 12E with a 4mb flash on it. I've had plenty of experience flashing them using esptool.py and esptool-ck, so I did what any self respecting person did.

Firstly, I wired a Serial -> USB Adaptor to it:

https://digistump.com/wiki/oak/tutorials/serialfirmware was a good primer for how to wire it and install esptool.py.

Make sure you connect P2 to ground, or the ESP8266 will not boot into serial flash mode.
My setup looks like this.

Then I backed it up using esptool.py:

python esptool.py --baud 115200 --port /dev/tty.SLAB_USBtoUART read_flash 0x000000 0x400000 flash_devicenumber.bin

You will definitely need to adjust the --port part of this command to suit your circumstances (COM on windows, usually /dev/tty. on mac and similar on linux) and make sure you put the device number or a friendly name in for your.bin file so if you ever have to go back you're not totally screwed.

Then, I wiped it with esptool.py:

python esptool.py --baud 115200 --port /dev/tty.SLAB_USBtoUART erase_flash

Again, change the port to whatever port your serial-usb adaptor shows up as on your relvant OS.

Your Digispark Oak is now Particle free

But it's still not entirely usable. At this point you could:

I expect most people will want the first option as it means you can use local or HTTP based Over The Air updating.

But we need to tell the Arduino ESP8266 Core about the Digispark Oak as the pin numbers on the board don't match what pins are being used on the ESP8266.

Telling Arduino about Oak's pins.

First thing you'll need to do is to create a variant in the hardware folder for the ESP8266 core. These instructions are assuming you've already installed the core.

On Windows 10, this is in your user's Documents folder. The full address will look something like:
C:\Users\Username\Documents\ArduinoData\packages\esp8266\hardware\esp8266\2.3.0\variants

On Mac, it's in your user's Library folder, so the location is:
/Users/<USERNAME>/Library/Arduino15/packages/esp8266/hardware/esp8266/2.3.0/variants

The version numbers may change when new releases of the core come out, so you will need to double-check.

To begin, unzip this zip file in the variants folder. This should create a folder called DigiStumpOak with a file inside it called Pins_Arduino.h . For those of you who'd rather not download a zip file, here's a gist with it.

Then, we will need to add some lines to boards.txt, which is in the folder above the variants folder.

At the end of the boards.txt file, add the following:

Congrats, you're done!

At this point, you can now reopen the Arduino IDE and you should end up seeing another board in your Boards menu under Tools.

I may submit this upstream as a new board definition for the Arduino ESP8266 core, but that will take a little bit to be added.

If you've found this useful, please let me know.

ESP8266 Experimentation

ESP8266 Experimentation

I've been working with ESP8266 based projects a lot lately, expect some writeups soon.

This gif is a Sonoff TH12 board running an 8-pixel ws2812 breakout.

HSBNE Meeting Attendance Swipe

HSBNE Meeting Attendance Swipe

The Meeting Attendance Swipe is a project I've built and iterated through over the last few months. It's an ESP8266 powered project that has an RFID reader in it for recording members' attendance at HSBNE.

Hardware

  • A Lolin esp8266 development board and base board.
  • A 3xAA battery pack.
  • A single WS2812b addressable RGB LED
  • A Seeedstudio Grove - 125KHz RFID Reader
  • A funky case based on Parametric Flexbox by bdahlem

Here's all the laser cut parts and the development board I originally was using but had issues using any particular pin for software serial.
Laser Cut Parts

And here it is while gluing together the case. I found out that the living hinges on the flexbox weren't great on 3mm acrylic and would break so I snapped them off cleanly.

Software

The software side of things is a very simple C program written in the Arduino IDE using ESP8266 custom board support.

On boot it connects to a wireless network and then waits for a serial message on a digital pin of the RFID tag swiped on the reader. It then massages this tag ID to remove the manufacturer code and CRC and then turn it into the decimal representation of the tag ID.

Once it has the tag ID in decimal format it sends it off to our access system and waits for a response, turning the WS2812b yellow. Based on that response it will then either turn the WS2812b green or red depending on whether or not the user is in the system and is paid up.

I've posted some example code below sans passwords to demonstrate how I implemented it in C.

/*
 *  Simple HTTP get webclient test
 */
#include <SoftwareSerial.h>
#include <ESP8266WiFi.h>
const char* ssid     = "wifissid";  
const char* password = "wifipassword";  
const char* host = "accessystemurl";  
SoftwareSerial swSer(4, 5, 128);  
String rawtag; // buffer string for data receive over serial port

void setup() {  
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(14, OUTPUT);
  Serial.begin(112500);
  delay(10);

  // We start by connecting to a WiFi network

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  swSer.begin(9600);
  Serial.println("Serial Started");
}


void loop() {

  while (swSer.available()) {
       delay(10);  
         if (swSer.available() >0) {
       char c = swSer.read();
       rawtag += c;}
       }

     if (rawtag.length() >0) {
     Serial.println(rawtag);
     String tagID = rawtag.substring(5,11);
     Serial.println(tagID);
     long tagIDDEC = hexToDec(tagID);
     Serial.println(tagIDDEC);
     checkcard(tagIDDEC);
     delay(3000);
     rawtag="";
     } 
}


void checkcard(long tagid) {

  // ++value;
  digitalWrite(13, HIGH);
  Serial.print("connecting to ");
  Serial.println(host);

  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }

  // We now create a URI for the request
  String url = "/logger.php?q=" + String(tagid) + "";
  Serial.print("Requesting URL: ");
  Serial.println(url);

  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  delay(10);

  // Read all the lines of the reply from server and print them to Serial
  digitalWrite(13, LOW);
  digitalWrite(12, HIGH);
  while(client.available()){
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }

  Serial.println();
  Serial.println("closing connection");
  digitalWrite(12, LOW);
}


unsigned long hexToDec(String hexString) {

  unsigned long decValue = 0;
  int nextInt;

  for (int i = 0; i < hexString.length(); i++) {

    nextInt = int(hexString.charAt(i));
    if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9);
    if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15);
    if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15);
    nextInt = constrain(nextInt, 0, 15);

    decValue = (decValue * 16) + nextInt;
  }

  return decValue;
}

As you can see in this version I'm missing the ws2812b controlling part, it should also be noted that I'm using a different softwareserial library than the default one on the Arduino IDE. You can find it at https://github.com/plerup/espsoftwareserial .

If you have any queries, please feel free to ask in the comments or poke me on social media.

Blogging 6.0

Blogging 6.0

This is my new blog, I've not been very good at documenting what I do historically so I'm going to change that with this.

Are you sitting on the edge of your seat?