Designing a power supply for the new trainer board

Many of you are using the Microcontroller Trainer v2 that I designed a couple of years ago. Those of you who develop projects with larger current demands understand the limitations of the LM317 linear voltage regulator that I used on that board, and have shared a desire for more current capabilities. I’ve been working on the next (and likely final) revision of the trainer board, aiming for it to become a permanently available product, and as part of this I wanted to design an enhanced power supply option.

So far, here’s how the design is going. The main trainer board itself will have a basic power supply included. This supply will once again be based on linear regulators, and will once again provide for a 5v and 3.3v rail. Current handling will be increased to roughly 1 amp per power rail, but I’m not stopping there.

For those of you who want more from a power supply ,I’m designing an enhanced power supply option. The enhanced power supply will be an add-on card for the trainer board, and will provide the following features

Support for an 18650 Lithium Polymer battery – so you’re no longer chained to the workbench

Real-time voltage and current monitoring of both power rails, with a separate microcontroller with integrated high-resolution color IPS display

Higher efficiency through the use of switching regulators

As I started to design the power supply, I looked at other products on the market. One that caught my eye in particular was the Adafruit Powerboost 1000c. Adafruit chose to use a Texas Instruments TPS6109x boost converter module on the output of a LiPO charge controller, which gives about 2 amps of capacity. This was perfect for what I was trying to accomplish with a 1 amp load per rail. Here is the datasheet for the TPS module from TI

https://www.ti.com/lit/ds/slvs484c/slvs484c.pdf

I’ve designed a couple of prototype power supplies using this module, and so far, it’s never worked. I can’t even get it working a little bit. I’ve cleaned the slate, and designed another supply from scratch, and I’m currently waiting on the stencil to arrive so I can assemble the unit. This was my first time having my board house create a purple PCB, the color is pretty cool – very similar to the boards coming out of OSHPark.

Unfortunately, the stencils aren’t here yet. The best I can get out of DHL is ‘shipment on hold’ – so maybe the PCBs made it through customs but the stencil didn’t ? I really don’t know.

I’ll be sure to keep you informed of the results of the power supply testing – maybe it’ll work this time? I’ll likely be live-streaming on twitch while assembling it, so be sure to tune and and watch the work in progress!

Video: Serially-Controlled LEDs made easy with the Microcontroller Trainer

I just posted a video to YouTube demonstrating how easy it is to use Serially-Controlled LEDs with Arduino using the Microcontroller Trainer. Check it out!

Example code (Courtesy of the Adafruit NeoPixel Library)

// A basic everyday NeoPixel strip test program.

// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
//   connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
//   a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN    6

// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 60

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)


// setup() function -- runs once at startup --------------------------------

void setup() {
  // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
  // Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
}


// loop() function -- runs repeatedly as long as board is on ---------------

void loop() {
  // Fill along the length of the strip in various colors...
  colorWipe(strip.Color(255,   0,   0), 50); // Red
  colorWipe(strip.Color(  0, 255,   0), 50); // Green
  colorWipe(strip.Color(  0,   0, 255), 50); // Blue

  // Do a theater marquee effect in various colors...
  theaterChase(strip.Color(127, 127, 127), 50); // White, half brightness
  theaterChase(strip.Color(127,   0,   0), 50); // Red, half brightness
  theaterChase(strip.Color(  0,   0, 127), 50); // Blue, half brightness

  rainbow(10);             // Flowing rainbow cycle along the whole strip
  theaterChaseRainbow(50); // Rainbow-enhanced theaterChase variant
}


// Some functions of our own for creating animated effects -----------------

// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
  for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
    strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip.show();                          //  Update strip to match
    delay(wait);                           //  Pause for a moment
  }
}

// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
  for(int a=0; a<10; a++) {  // Repeat 10 times...
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in steps of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show(); // Update strip with new contents
      delay(wait);  // Pause for a moment
    }
  }
}

// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
  // Hue of first pixel runs 5 complete loops through the color wheel.
  // Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
  // means we'll make 5*65536/256 = 1280 passes through this outer loop:
  for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
    for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
      // Offset pixel hue by an amount to make one full revolution of the
      // color wheel (range of 65536) along the length of the strip
      // (strip.numPixels() steps):
      int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
      // strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
      // optionally add saturation and value (brightness) (each 0 to 255).
      // Here we're using just the single-argument hue variant. The result
      // is passed through strip.gamma32() to provide 'truer' colors
      // before assigning to each pixel:
      strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
    }
    strip.show(); // Update strip with new contents
    delay(wait);  // Pause for a moment
  }
}

// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait) {
  int firstPixelHue = 0;     // First pixel starts at red (hue 0)
  for(int a=0; a<30; a++) {  // Repeat 30 times...
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in increments of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {
        // hue of pixel 'c' is offset by an amount to make one full
        // revolution of the color wheel (range 65536) along the length
        // of the strip (strip.numPixels() steps):
        int      hue   = firstPixelHue + c * 65536L / strip.numPixels();
        uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show();                // Update strip with new contents
      delay(wait);                 // Pause for a moment
      firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
    }
  }
}

A WiFi Bitcoin Ticker with the WEMOS D1 Mini

So I got a WEMOS D1 Mini in my Hackerboxes 0023 monthly subscription box, and hadn’t done anything with it yet. I’ve been playing with crypto-currency stuff lately, and decided it would be nice to have a small bitcoin price ticker that I could stick somewhere. So I found some code online, put a few ideas together, and here’s what I’ve come up with. Using the WEMOS D1 Mini, and the OLED display for it, I’ve written an Arduino sketch that will go fetch the Bitcoin/USD price every 30 seconds from Coinbase. You’ll need to load a few libraries, namely the ArduinoJSON, AdaFruit_SSD1307, and the AdaFruit GFX Library. Also, since this is an ESP8266, you’ll need those board definitions (don’t worry, I’ll try and record a walk-through video of all these steps at a later point). I’ve got some serial debugging stuff in here too, so you can monitor the serial port if something is going sideways. But for now – the code.

/

#include <SPI.h>
#include <Wire.h>
#include <ESP8266WiFi.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ArduinoJson.h>
//Coindesk Configuration
const char* host = "api.coindesk.com";
//WiFi Configuration
const char* ssid = "yourSSID";
const char* password = "yourWiFiPassword";
#define OLED_RESET 0
// GPIO0 Adafruit_SSD1306 display(OLED_RESET);
#if (SSD1306_LCDHEIGHT != 48) #error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup() {
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 64x48)
// Begin the Wifi Connection WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

display.clearDisplay();
display.display();
delay(2000);
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: "); Serial.println(WiFi.localIP());
display.setTextColor(WHITE);
display.setTextSize(2);
display.setCursor(0,0);
}

void loop() {
Serial.print("connecting to ");
Serial.println(host);
WiFiClient client;
const int httpPort = 80;
if (!client.connect(host, httpPort)) { Serial.println("connection failed");
return;
}

String url = "/v1/bpi/currentprice.json";
client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n");
delay(100);
String answer;
while(client.available()){
String line = client.readStringUntil('\r');
answer += line;
}

client.stop();
Serial.println();
Serial.println("closing connection");
String jsonAnswer;
int jsonIndex; for (int i = 0;
i < answer.length();
i++) { if (answer[i] == '{') {
jsonIndex = i; break;
}
}
jsonAnswer = answer.substring(jsonIndex);
Serial.println();
jsonAnswer.trim();
int rateIndex = jsonAnswer.indexOf("rate_float");
String priceString = jsonAnswer.substring(rateIndex + 12, rateIndex + 18);
priceString.trim();
float price = priceString.toFloat();
Serial.println();
Serial.println("Bitcoin price: ");
Serial.println(price);
int intPrice;
intPrice = (int) price;
display.clearDisplay();
display.setCursor(0,0);
display.println("BTC");
display.println(intPrice);
display.display();
delay(30000);
}

When you’re done, you’ll have something a bit like this