World’s Crappiest Oscilloscope… v1

When Ms Geek gave me an Arduino Leonardo to play with, one of the first things I did was go through the examples. After almost two decades of experience with PICs, I was amazed at how easy it was to get things like serial communication and ADC working. Don’t get me wrong – I’m still a PIC guy… but I think I’m an Arduino guy now, too.

The ReadAnalogVoltage example caught my attention because it was so simple. Here’s the setup. It’s just a potentiometer with one end terminal connected to +5v and one to GND, and the wiper connected to A0:

Not much to it, eh? That bent yellow wire in the middle just holds the Leonardo in place.

I played around with it for a while and watched the output on the Serial Plotter, but then I had a thought. You need to run the Arduino software to use the Serial Plotter, and besides, the Serial Plotter looks too nice. Half-remembered days of coaxing dusty old VT100 and TN3270 terminals back to life and running a BBS made me think – I could do the same thing, but not as good!

I dug through some of my old PIC programs and found a serial terminal that I wrote back in 2002. Between that and the ANSI sequences at http://ascii-table.com/ansi-escape-sequences.php, I stapled together a really bad looking display that I like to call the World’s Crappiest Oscilloscope, v1. Here’s the program:

// World's crappiest oscilloscope v1
// Borrows heavily from ReadAnalogVoltage example in the Arduino Examples menu
// Uses Arduino Leonardo, reads voltage on analog pin A0, then uses good old ANSI
// codes to
// draw a really bad oscilloscope in a serial terminal.
// A little amusing but very useless.
// Info about ANSI codes is at http://ascii-table.com/ansi-escape-sequences.php
// **THIS PROGRAM IS FREE TO USE AND MODIFY AS YOU SEE FIT**

void setup() {

  pinMode(A0, INPUT); // Set pin A0 to input.

  Serial.begin(9600); // initialize serial communication at 9600 bits per second.

  delay(3000);  // Should be enough time to start up a serial terminal.

  // Warm up the tubes...
  Serial.write(27); // Clear terminal screen with ESC [2J and ESC is ASCII 27
  Serial.print("[2J");
  Serial.println("Warming up the tubes, please wait...");
  delay(2000);  // This just here for dramatic effect.
  Serial.println("Starting...");
  delay(2000);  // This also just here for dramatic effect.
}


void loop() {

  // Now set up the fancy oscilloscope screen. Ah, the good old ANSI days...

  // Set Oscilloscope screen to white markers on black background.
  Serial.write(27);
  Serial.print("[0;37;40m");
  
  Serial.write(27);  // Clear Terminal screen with (esc)[2J, (esc) is ASCII 27
                    // Serial.write sends binary data to the serial port
  Serial.print("[2J");
  Serial.write(27); // ESC again.
  Serial.print("[H"); // cursor to home.

  // The following lines draw the scale up the left side of the terminal screen and
  // the bottom border.
  Serial.print("5.00V|\r\n");
  Serial.print("4.75V|\r\n");
  Serial.print("4.50V|\r\n");
  Serial.print("4.25V|\r\n");
  Serial.print("4.00V|\r\n");
  Serial.print("3.75V|\r\n");
  Serial.print("3.50V|\r\n");
  Serial.print("3.25V|\r\n");
  Serial.print("3.00V|\r\n");
  Serial.print("2.75V|\r\n");
  Serial.print("2.50V|\r\n");
  Serial.print("2.25V|\r\n");
  Serial.print("2.0V0|\r\n");
  Serial.print("1.75V|\r\n");
  Serial.print("1.50V|\r\n");
  Serial.print("1.25V|\r\n");
  Serial.print("1.00V|\r\n");
  Serial.print("0.75V|\r\n");
  Serial.print("0.50V|\r\n");
  Serial.print("0.25V|\r\n");
  Serial.print("0.00V|________________________________________________________________________________\r\n"); // 80x _
  Serial.print("                         WORLD'S CRAPPIEST OSCILLOSCOPE v1\r\n");

  byte ColumnCount = 7; // Okay, there are 50 columns to put data into, starting at column 7 and ending at 57.

  while (ColumnCount <= 87){
    int sensorValue = analogRead(A0); // read the input on analog pin 0. Need to use an int because it's a 10-bit number.
    
    float voltage = sensorValue * (5.0 / 1023.0); // Convert the reading (which goes from 0 - 1023) to a voltage (0 - 5V).

    int OscOut = (voltage * 4);  // so far so good but need to make it go the other way
 
    OscOut = 21 - OscOut;

    // now, staple everything together into one string to control the cursor
    // Control cursor position: ESC then [line;columnH
    
    String OscStr;
    OscStr = '[';
    OscStr = OscStr + OscOut;
    OscStr = OscStr + ';';
    OscStr = OscStr + ColumnCount;
    OscStr = OscStr + 'H';

    Serial.write(27);

    // Just for kicks, let's try to change the trace colour to green.
    Serial.print("[0;32;40m");

    Serial.write(27);

    Serial.print(OscStr);
    Serial.print("*");

    ColumnCount = ColumnCount +1;
  
    delay(50); // wait a bit before going back so the screen doesn't fly by too quickly.
  }

}

I really need to figure out how to widen the blocks in this theme… it kind of mangles the formatting. If you copy and paste it directly, it still works though. This is what it does (don’t start the video unless you have a strong heart – it’s THAT amazing):

I wonder if there actually were any of those old terminals set up with something like this back in the day…

It’s Not Lupus

I stumbled across this yesterday – it’s right out of the pilot episode of House M.D.:

Surgeons opened her skull to remove a cancer tumour – then they saw a tapeworm” – nationalpost.com, June 7 2019

Disgusting, fascinating, and ultimately good news – the victim says her symptoms have gone away “almost 100 percent”.

Remember, folks – wash your hands and cook your pigs.

Fixed The Old Weather Station

I got a nice little weather station as a gift about a decade ago. It’s been pretty accurate and the display is usually nice and bright and colourful. Over the last while, however, the backlight has gone from bright, to flickering, to flashing once in a while, to completely dead. This made the unit almost useless unless it was daytime and you were standing right in front of it.

Today I cracked it open and gave fixing it a shot. It came apart pretty easily, but I learned later that with the problem I had that I didn’t need to remove the green circuit board. Removing it led to a lot of frustration and grief as it took me many tries to get everything lined up again.

Anyway, it turned out that there were two problems. One was that one of the wires wasn’t actually soldered to the backlight – there was a glob of solder and the wire was just resting against it. I thought that’d be an easy fix but unfortunately, it didn’t make any difference.

What I ended up doing was ignoring the original LED driver circuitry altogether and connected it to the power jack (tip positive). I put a two-pin female header in series to I could easily try different resistors:

1K was a little dim, 100 ohms was better, but I finally settled on 47 ohms. That made for about 110mA, well within a regular 1/4W resistor’s capacity, and considering there are four LEDs in parallel, that’s about 28mA per LED – nice and low. I’m pretty pleased with how it’s working at this point:

Nice and bright

Still, I’m going to run it for a few days to make sure that the resistor and backlight aren’t warming up before I solder the resistor in permanently and button the whole thing back up.

Hopefully this means I’ll get at least another ten years out of it.

Getting Two I2C Displays Working At Once On An Arduino

Ms Geek gave me an Arduino Leonardo a little while ago and from the moment she showed me how to get it to blink an LED, I’ve been hooked. I’ve been in the PIC camp for almost 20 years now, but the build environment and ease of use of the Arduino blew my mind and I’ve been tinkering with them every day since that little “L” LED blinked.

One of the things I wanted to do was get a display working. I played around with some of the old HD44780 LCDs that have been collecting a very thick coat of dust and they worked well enough, but something I’ve never done is use a graphic display. TFT displays were always expensive (and still kind of are), but nowadays there seems to be quite the selection of small OLED displays that are quite inexpensive.

I did some shopping around and found a deal on some 128×32 pixel displays as well as one 128×64 pixel display, both of which speak I2C. It was pretty easy getting them working with the Leonardo and the u8g2 library, and while you can fit a surprising amount of information on even a 128x32px display, I have some other ideas for other projects where it would be useful to have two displays working at the same time.

Here are the two displays I wanted to use. On the left is the 128x64px display that has a SH1106 controller, on the right is the 128x32px display that has an SSD1306 controller. Both are 5V tolerant, so they’re easy to connect to the Leonardo. The origin is the same on both – at the top left of the display.

One of the nice things about I2C is that you can select individual devices by address. No extra wires needed, just send the right signals down the wires and you’re talking to whichever device you’d like. The flexibility of addressing in I2C has its drawbacks, though. If you want to use multiple devices without any external circuitry, each device needs a different address.

Both of the displays came configured with the same address – 0x78 (or 0x30 if you’re treating it as a seven-bit address). The 128x32px display doesn’t seem to have any way to change the address, but by moving a tiny surface-mount resistor on the 128x64px display, I was able to change the address from 0x78(0x30) to 0x7A(0x3C):

Believe it or not, I’ve been soldering for 35 years and I’ve taken high-reliability soldering courses, but that was back in the day when my eyes still focused well, my hands didn’t shake, and the nerves in my right arm were still working properly. Hooo boy it was pretty frustrating to move that resistor over. On this display it was 4k7, next time I may just use a 1/4 watt resistor instead of the SMD. Regardless, my crappy soldering was good enough to change the address of the display.

Hooking everything up was easy. The Leonardo has breakout pins for hardware SDA and SCL lines, but I have some Pro Micro and Nanos that I’d like to use so I used the numbered digital pins instead (obviously, if you’re using something other than the Leonardo, you’ll need to check the pinout of your device for the right pins). In the Leonardo’s (and Pro Micro’s) case, the I2C pins are 2(SDA) and 3(SCL). It’s possible that 4k7 pullups might be needed on the SDA and SCL pins when using more than one device; in this case things seemed to work fine without them. Here it is, in all it’s connected glory:

I frequently leave the film protectors on stuff I buy. Makes me think that it’s still brand new, even when it’s not.

So, with two displays with different I2C addresses hooked up, I was able to get each one working individually just by changing the constructor and address. Getting both working at the same time took a little bit of work, but the Arduino Wire and u8g2 library reference pages and example programs had the information I needed. Here’s the program:

// LEONARDO - TWO I2C OLEDS
// Using two displays: the 128x64 SH1106 OLED (0x3C/0x78), and the 128x32 SSD1306
// (0x3D/0x7A).
// The 128x64 display will be DISPA, the 128x32 display will be DISPB.
// This program is a bit of a pig, using 60% of the program storage space and 95% of
// the dynamic memory.
// Sometimes when running this program, the Leonardo doesn't respond to serial port
// data/uploads. If that happens, start the compile/upload, immediately ground the
// RESET pin very briefly, and it should work.
// **THIS PROGRAM IS FREE TO USE AND MODIFY AS YOU SEE FIT**

// Need this to use the I2C bus. I2C pins on Leonardo are broken
// out but are also 2 (SDA) and 3 (SCL).
#include <Wire.h> 

// Need this to make displays do things and stuff.
#include <U8g2lib.h> 

// Select proper constructor (driver) for this particular 128x64 OLED display and
// call it DISPA. See https://github.com/olikraus/u8g2/wiki/u8g2setupcpp for other
// drivers. There are lots of different OLED board configurations out there!
U8G2_SH1106_128X64_NONAME_F_HW_I2C DISPA(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
                                                                              
// Select constructor for this particular 128x32 OLED display, call it DISPB.                                                                               
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C DISPB(U8G2_R0, U8X8_PIN_NONE);

// Set aliases for the I2C pins. They're broken out on the Leonardo but I'm using
// the numbered pins so it's seamless with other boards like the Pro Micro.
#define SDA 2  
#define SCL 3


void setup() {
  // put your setup code here, to run once:

  // Setting the pins that control the displays to all outputs. There are no inputs
  // on these two OLED displays to worry about - others may be different!
  pinMode(SDA, OUTPUT);  
  pinMode(SCL, OUTPUT);


  // Set I2C bus speed on Arduino and both displays. This may not be necessary
  // but I put it in anyway - one less thing to troubleshoot if things don't work.
  Wire.setClock(100000);
  DISPA.setBusClock(100000);
  DISPB.setBusClock(100000);

  // Some devices say they're 0x78/0x7A, but others may say they're 0x3C/0x3D. It's
  // like that because the address is 7 bits but some places (u8g2 included) pad it
  // out to 8 bits. Adding a 0 on the end multiplies the value by 2.
  // Most of the small OLED displays out there seem to be set to 0x3C(0x78). Some
  // can be changed, but not all of them.
  // See https://www.arduino.cc/en/Reference/Wire for details.
  DISPA.setI2CAddress(0x7A);
  DISPB.setI2CAddress(0x78);
  
  // Fire up the displays and get them ready to accept data.
  // Remember, DISPA is the 128x64px OLED, DISPB is the 128x32px OLED.                           
  DISPA.begin();
  DISPB.begin();

  // Select a font to use on DISPA and DISPB. They don't have to be the same, and
  // you can change them throughout the program, too. 
  // Check https://github.com/olikraus/u8g2/wiki for others, there are LOTS.
  DISPA.setFont(u8g2_font_logisoso30_tf );
  DISPB.setFont(u8g2_font_logisoso30_tf );

  // Let's put some writing on DISPA. Make sure the display buffer is clear before
  // writing or drawing anything.
  DISPA.clearBuffer();

  // Move the starting position of what will be written/drawn next to x=0, y=32.
  // As shown in the above picture, coordinates start at 0,0 at the top left.
  // If you want to properly display text, make sure you set the y-value to at least
  // as large as how many pixels tall your font is.
  // If your display shows nothing, make sure you have set the y-value or everything
  // will end up being drawn beyond the edges of the display...
  DISPA.setCursor(0, 32); 
  
  // This just puts Howdy! in the selected font in the buffer. Nothing gets written
  // to the screen yet. You could move the cursor position again and write more text
  // to the buffer or draw some shapes if you wanted. At this point you're just
  // setting bits that will turn on the associated pixels.
  // See https://github.com/olikraus/u8g2/wiki/u8g2reference to find out how to
  // draw shapes and lines or even set individual pixels.
  DISPA.print("Howdy!");  

  // Take whatever's been written or drawn in the buffer and send it to the display.
  DISPA.sendBuffer(); 

  // Now, do the same thing for DISPB.
  DISPB.clearBuffer();  
  DISPB.setCursor(0, 31);
  DISPB.print("Hi!");
  DISPB.sendBuffer();

  delay(2000);  // Wait two seconds to admire the displays before moving on.

}

void loop() {
  // put your main code here, to run repeatedly:

  // All this code does is say "HELLO" and show a count up on DISPA, while 
  // counting down on DISPB.

  byte CountUp = 0;
  while (CountUp <= 255) {
    DISPA.clearBuffer();
    DISPA.setCursor(0, 31);
    DISPA.print("HELLO");
    DISPA.setCursor(40, 63);
    DISPA.print(CountUp);
    DISPA.sendBuffer();

    DISPB.clearBuffer();
    DISPB.setCursor(40, 31);
    DISPB.print(255 - CountUp);
    DISPB.sendBuffer();
    CountUp = CountUp + 1;
    delay(100);
  }
  delay(500);  // Wait 500ms and do it again.
}

Here’s what it looks like when it’s running:

I am not a programmer, but there’s really not all that much to this particular project. Like I mention in the code, sometimes when the Leonardo is running this program, the Arduino programmer won’t be able to connect with the board. My guess is that it’s because almost all of the memory is used up, but I’m not sure. Anyway, what you need to do is start the compile/upload, immediately ground the RESET pin briefly (a quick tap will do), and watch the screen. Sometimes I have to do it more than once, but don’t panic if your board isn’t responding – it’s not dead.

I’ve only tried this on the Leonardo and the Pro Micro, both of which use the ATmega32u4 MCU.

Signs Of A Clogged Printer Nozzle

I’ve been fighting with my printer for a couple of days now because the nozzle keeps clogging. After changing out the nozzle and cleaning the hotend, it would run fine for a while and then start to plug up again. The printer has seen a lot of heavy use with different materials over the past six months, so I suppose I don’t blame it.

I think I’ve got it fixed now, but you can’t ever really have 100% confirmation that the crud is all gone. It may print well for the next one, two, or twenty prints, then clog again.

Signs that your printer is developing a clog:

  • You find you have to make changes to feed rate or flow settings that you didn’t before.
  • Extrusion (particularly first layer) doesn’t look consistent.
  • There is a roughness to horizontal and vertical skins that wasn’t there before.
  • Printed parts are more fragile than usual.
  • Lots of horizontal, “dotted” lines along the sides of the print.
  • You can hear an odd scraping sound coming from the extruder (the extruder gear is grinding plastic because it can’t push it in fast enough).
  • There is a lot more dust than usual around the extruder gear/motor (same reason as above point).
  • The motor driving the extruder keeps “thumping” or “popping” and jumping backwards because it can’t keep up with the electronics that make it turn.
  • The filament spool is not turning.

If you’re suspicious that there’s a clog, level your print bed and do a test print (you would be amazed at how many things can be fixed just by levelling the bed). If it’s still not printing properly, raise the nozzle from the bed (the further, the better), and extrude a bunch of filament, making sure to keep cutting it so it doesn’t touch the print bed and make the filament bend or twist. If the extruded plastic is pointed straight down, is consistent along its length, and is the appropriate thickness, things may be okay. Here are some samples from a test extrusion I did that showed there was definitely some junk stuck in there somewhere:

Filament with a lot of moisture in it can extrude like this. I dry my filament regularly and use a lot of dessicant so it’s probably junk in the nozzle.
This looks more like a clog.
Again, could be damp filament… could be junk floating around in the nozzle.
This is DEFINITELY a clog.

Another thing I do to help me keep an eye on things is mark one or two spokes on the filament spool with a colour that stands out (silver on a black spool, black on a white spool, etc). That way, I can note where the marked spokes are, leave the room, and come back later to see if they’ve moved.

I hope I’ve got it cleared out. If there is still any junk in there, it would be nice if it either melts or is small enough to fit through the nozzle. I have a spare (brand new) hotend, so if I need to I can swap it out and give the used one an even more thorough cleaning.