RC1 Boards for the Electronics Trainer are almost here

Project: Blue Smoke Monster Electronics Trainer Release Candidate 1

Just a quick sneak preview of the Release Candidate 1 PCB’s for the Electronics Trainer. The following are some of the enhancements over the Rev 2.0 trainer board

I’ve re-designed the power supply to provide for more current. We haven’t done performance testing yet (it’s coming!) but we’re aiming to provide a full 1 amp of current on both the 3.3 volt and the 5 volt rail of the board.

I’ve replaced the ESP32 USB Devkit C footprint with an Adafruit Feather-Compatible footprint. This means that instead of just a single MCU in the slot, we can support dozens of MCUs available in the Feather-Compatible footprint, all without taking up space on the breadboard. The folks over at Adafruit have already created dozens of MCUs in this footprint, and we don’t see them slowing down. As new MCU’s are supported, we expect future compatibility by using this Feather-Compatible footprint.

I’ve added 4 user-controllable LEDs. These LEDs can come in handy to represent the logic state of a signal line on a project being developed on the trainer, so we make it simple for you. We handle current limiting for you, so just throw a positive voltage at the LEDs, and enjoy basking in the glow.

I realized that I wanted an easier way to connect other ‘benchtop stuff’ to the circuits under development on the trainer board, so I added 4 banana jacks (and the board supports the standard double-BNC spacing, if you need to connect double-banana plugs). This can be a great way to connect a multimeter to the board, or maybe something like a DC load. ; anything with banana plugs, really.

Along those same lines, I wanted a way to connect instrumentation to the trainer board – things like an oscilloscope. To facilitate this, I added two 50 ohm BNC jacks. You can very easily wire your scope, or something like an RF signal generator, a function generator, the sky is the limit.

I decided to enhance the rotary encoders by adding onboard resistors. This is one less thing you have to deal with when using rotary encoders with your project.

I wanted to give you the ability to support some somewhat-higher current switching with your MCU, so I’ve added 4 N-channel mosfets. These are ideal for use as ‘MOSFET as a switch’

I’ve added a high-stability real-time clock (The Dallas DS2321) to allow for precision timekeeping for your projects. I find that so many of my projects can benefit from precision timekeeping, this was a no-brainer to add.

I wanted a way to future-proof the trainer so that we could add user-provided components or circuits without taking up breadboard space. To do this, I created a User Expansion Socket. Essentially, I give you 40 pins to use however you want – and you (or I) can design plug-in modules. This could be an easy way to add a non breadboard-friendly MCU, or some other off the shelf part to the trainer.

I enhanced many of the headers on the board. I decided to surround the breadboard with double-row headers instead of single-row headers. This helps to reduce the need to use the breadboard for the occasion when you need to connect 3 ‘nodes’ together – it REALLY reduces the number of jumper wires you’ll use for many projects. I haven’t done this EVERYWHERE, but I did it in the places I felt it brought the most value.

Taking things farther

In addition to the on-board feature enhancements, I’ve also designed a advanced power supply, that will be optional, that really ramps up the power supply features by a long shot. First, it’s switching based, so it’s very high-efficiency. Second, it’s built to support an on-board LiPO (I used an 18650, but I plan to provide options to connect other battery types) to allow you to take your project mobile. No longer are you glued to the bench! Third, I’ve developed a custom voltage and current monitoring system. I provide support for a dedicated MCU to monitor and visualize (on a nice color IPS display) for each of your power rails. I also have some advanced features in mind (can anybody say ‘serial monitor’) and of course, it’ll be hack-able and extensible – so you can make it do whatever you want it to do!

I’m really excited with the new features and enhancements, and I need your help to take this from the prototyping stage, and make it a reality. Here’s how you can help. Share this project with friends! If you already have a trainer board, show us the projects you’ve been prototyping – post them on youtube! The electronics trainer is intended to be an educational tool – and I’m already working on creating content for more than 100 projects that you’ll be able to prototype with the product. More on that in future posts.

Check me out on twitch – I’ll be streaming much of the next steps in testing the prototype.

http://www.twitch.tv/bluesmokemonster

Thanks for staying tuned, and click the link at the top of the page (in the menu) to sign up to be notified of updates as we prepare for our Kickstarter!

Keep experimenting, keep learning, and don’t be afraid to let the magic smoke out from time to time. That’s when the learning happens.

Josh

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