ATtiny85 MIDI Tester

January 25, 2019 at 10:28 pm (maker, music) (, , )

Having spent some time messing about with building simple synthesizer circuits, I’m putting together a simple MIDI to CV converter.  I have one using an ATtiny85 but think I’m struggling from the fact it is only using SoftwareSerial, so I plan to have another go with an ATtiny231w pretty soon now.

One thing I was missing though was a simple “hands free” MIDI tester.  Now it would be fairly simple to hook up my laptop or a keyboard to a MIDI cable and use that, but I wanted something I could just plug in and leave sending MIDI data out to whatever I was building.  So the idea of using a simple USB-powered ATTiny85 to creating a continuous set of MIDI note on and not off messages was born.

I’m using one of those cheap Digispark USB clones you can buy. I had no luck ever getting the USB programming side of it to work, (its supposed to be able to have the nucleus boot loader installed to provide a software USB implementation), but its easy to programme if you have an 8-pin DIL test clip, in my cased hooked up to a sparkfun tiny programmer.

2019-01-25 21.22.26

Basic design notes for the board:

  • P1 (equivalent to Arduino D1 and the ATtiny85 pin 6) has the built-in LED.
  • I’m using P2 as MIDI TX and P3 as (unused) MIDI RX (D2 and D3, mapped to ATtiny85 pins 7 and 2).
  • P0 (ATtiny85 pin 5) as a digital input with internal pull-up resistors enabled.

I’m using a simple MIDI out circuit from the Internet that shows:

  • DIN pin 5 – MIDI OUT signal directly connected to P2.
  • DIN pin 2 – MIDI ground.
  • DIN pin 4 – MIDI +5v via a 220R resistor.

The resistor was soldered inside an in-line female MIDI DIN socket.

2019-01-25 21.36.522019-01-25 21.42.10

A switch was soldered across from P0 to GND on the Digispark board.  The code will flash the LED when the switch is registered so you know you’ve done something.

That is pretty much it.

2019-01-25 21.51.47

2019-01-25 21.51.56

In terms of code, I just tested it with an increasing scale of a few octaves, with the switch being used to increase the tempo (by reducing the delay between notes). Of course, you can use whatever test pattern works for you.

My initial (simple) code below.

Important: You must “set the fuses” to use the internal 16MHz clock in order to get the MIDI baud rates for the SoftwareSerial implementation.

Kevin

// MIDI Code Test Generator using ATtiny85
// NB: Use Sparkfun USB ATtiny85 Programmer
//     Set Arduino env to USBTinyISP
//     Set 16MHz Internal Clock (required for MIDI baud)
#include <SoftwareSerial.h>

// Pin Mapping for DigiSpark USB/ATtiny85
//  P0 = PB0/D0 = Pin 5 Attiny85
//  P1 = PB1/D1 = Pin 6 - built-in LED
//  P2 = PB2/D2 = Pin 7
//  P3 = PB3/D3 = Pin 2 - wired to USB+
//  P4 = PB4/D4 = Pin 3 - wired to USB-
//  P5 = PB5/D5 = Pin 1 - wired to RESET
//
// Use the Arduino D numbers below (which are the same as Digispark P numbers)
#define MIDITX   2
#define MIDIRX   3
#define BUTTON   0
#define BLTINLED 1

// MIDI Parameters for testing
#define MIDI_CHANNEL     1
#define MIDI_LOWNOTE     36
#define MIDI_HIGHNOTE    90
#define MIDI_VELOCITY    64
#define MIDI_DELAYMAX    550
#define MIDI_DELAYMIN    50
#define MIDI_DELAYSTEP   100

#define MIDI_NOTEON      0x90
#define MIDI_NOTEOFF     0x80

SoftwareSerial midiSerial(MIDIRX, MIDITX);

int delayRate;
int buttonState;
int lastButtonState;
byte midiNote;

void setup() {
  // Switch will trigger HIGH->LOW
  pinMode (BUTTON, INPUT_PULLUP);
  pinMode (BLTINLED, OUTPUT);
  digitalWrite (BLTINLED, LOW);
  buttonState = HIGH;
  lastButtonState = HIGH;
  
  midiSerial.begin (31250); // MIDI Baud rate

  delayRate = MIDI_DELAYMAX;
  midiNote  = MIDI_LOWNOTE;
}

void loop() {
  buttonState = digitalRead (BUTTON);
  if ((lastButtonState == HIGH) && (buttonState == LOW)) {
    ledOn();
    delayRate = delayRate - MIDI_DELAYSTEP;
    if (delayRate < MIDI_DELAYMIN) delayRate = MIDI_DELAYMAX;
  }
  lastButtonState = buttonState;

  midiNoteOn (MIDI_CHANNEL, midiNote, MIDI_VELOCITY);
  delay (400); // Need note on long enough to sound
  midiNoteOff (MIDI_CHANNEL, midiNote);
  delay (delayRate);

  midiNote++;
  if (midiNote > MIDI_HIGHNOTE) midiNote = MIDI_LOWNOTE;
  
  ledOff();
}

void midiNoteOn (byte midi_channel, byte midi_note, byte midi_vel) {
  midiSerial.write (midi_channel+MIDI_NOTEON);
  midiSerial.write (midi_note);
  midiSerial.write (midi_vel);
}

void midiNoteOff (byte midi_channel, byte midi_note) {
  midiSerial.write (midi_channel+MIDI_NOTEOFF);
  midiSerial.write (midi_note);
  midiSerial.write ((byte)0);
}

void ledOn () {
  digitalWrite (BLTINLED, HIGH);
}

void ledOff () {
  digitalWrite (BLTINLED, LOW);  
}

Advertisements

Permalink 1 Comment

Arduino Nano “USB Device Not Recognised” Fix

January 19, 2019 at 5:06 pm (maker) (, , , )

I have quite a range of Arduino Nano boards of varying vintage, but I’ve found some always come up with “USB Device Not Recognised” in Windows and wanted to work out why.  Symptoms are:

  • all fine if powered externally or via the ISP header.
  • “USB Device Not Recognised” errors otherwise.

These are Arduino Nano v3.0 boards I believe, and it turns out there is a known issue where the TEST pin of the FTDI chip isn’t correctly grounded, which makes the boards unreliable at best, and constantly failing at worst.

The faulty boards look like this:

arduino nano ftdi - toparduino nano ftdi - bottom

Notice the FTDI chip on the bottom of the board – this is the cause of the issue.  Many of the other cheap clones of the Arduino Nano use the CH340 chip, these don’t seem to have a similar issue.  For reference, they look like something like this instead:

arduino nano ch340 - bottom

The fix for the issue is described here on the Arduino Forums: http://forum.arduino.cc/index.php/topic,23025.0.html

But you will need your soldering iron and a very steady hand (and probably a magnifying glass).  Basically the poster shorted pins 26 (TEST) and 25 (AGND) on the chip and that seems to do the trick.  These pins (3rd and 4th from the top right hand side of the chip) are highlighted below (see the FT232RL datasheet for details).

arduino-nano-ftdi-fix.jpg

ftdi-ft232rl-pinout

Attempt the fix at your own risk of course.  Double check the part number of the chip, the orientation with the spot and the datasheet for the part number you are reading on the chip before you go near the soldering iron.

It worked for me.  YMMV.

Kevin

 

Permalink Leave a Comment

Dual ScrollPhatHD 17×14 LED Array

January 13, 2019 at 12:31 pm (maker) (, , , , , )

Having now had a play with my ScrollPhatHDs with the Arduino I’ve now successfully linked two together via a TCA9548A breakout board (having solved my Weird Multi-I2C Bus Issues as previously described).

The ultimate aim was to make a self-contained unit containing two ScrollPhatHD boards, an Arduino Nano and the TCA9584A.  I’ve now managed that using a square piece of breadboard, various jumper wires and most importantly, the Pimoroni Pogo-a-go-go Solderless header pins – I just didn’t want to spoil the neat look of the ScrollPhatHD’s by soldering to them directly.  The Pogo-pins are just perfect for spring-loaded connections between the ScrollPhatHDs and breadboard.

The one quirk, is that if I wanted all boards nicely sandwiched between the ScrollPhatHDs and the breadboard, but wanted to use the pogo-pins, then the breadboard needs to be strip-side up.

Here is the plan, followed by some photos of the finished item.

scrollphat-breakout_bb

I’ve left the nano and tca breakout off, so I can see the tracks.  This was from a first experiment with the two Phats, so it already had three full height sets of cuts in tracks – hence the few places where there were a couple of bits of patching to do, which were just done with solder links.  There are a few pins added to support the nano, especially at the USB end where I’ll be plugging in and out, which aren’t connected to anything on the stripboard.  And the four pins highlighted for the two ScrollPhat’s themselves weren’t soldered pins – that is the location for the pogo-pins.

In the final board, I put the jumper wires on the underside, and used headers pushed right through from below.  I also added a reset switch (not shown in the plan) wired to the Nano RST and ground on the strip board.

The linking of the two Phats isn’t perfect – the Nano USB port is just a fraction too high to perfectly fit, meaning the two boards bow out slightly in the middle.  Note the use of the pogo-pins.  I could replace them all with a slightly longer stand-off, but this is fine for a prototype.

Also, I made sure to drop some insulating tape on the bottom of both the Nano and the TCA board, to make sure it wouldn’t short anything on the copper of the stripboard.  I also put a bit around the shield of the USB port just in case, but I don’t think there was anything conductive on the back of the Phat.

So I now have a USB-accessible, self-contained, programmable 17×14 LED array.

Software wise, this uses the modified Adafruit IS31FL3731 Library I mentioned before, with the added quirk that one of the boards needs the coordinates reversing.  Coupled with the need to switch boards using the TCA as well, this means the basic idea of using the board is as follows:

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <ScrollPhat_IS31FL3731.h>

// ScrollPhats connected using a TCA9548A I2C Multiplexer
// These are the I2C bus numbers used
#define TCAONE       0
#define TCATWO       1

//  HOR = number in horizontal (x) plane
//  VER = number in vertical (y) plane
#define HOR 17
#define VER 14

// Scrollphats have a hardcoded I2C address.
// Assumes connected as follows:
//      ledmatrix1 - using SC0 via the TCA
//      ledmatrix2 - using SC1 via the TCA
ScrollPhat_IS31FL3731 ledmatrix1 = ScrollPhat_IS31FL3731();
ScrollPhat_IS31FL3731 ledmatrix2 = ScrollPhat_IS31FL3731();

#define TCAADDR 0x70
void tcaselect(uint8_t i) {
  if (i > 7) return;
 
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();  
}

void setup () {
  // Initialse the I2C handling
  Wire.begin();
  
  tcaselect(TCAONE);
  ledmatrix1.begin();
  tcaselect(TCATWO);
  ledmatrix2.begin();
    
  // Do something to initialse your pixel array
}

void loop () {
  // Do stuff on your pixel array
  // Don't forget to write the displayRead(x,y) function
  // used in the scan routine

  ScanDisplay();
}

// Note: you need to implement the displayRead (x,y) function
//      to determine if a pixel is on or off
//
void ScanDisplay () {
  // Scan the first matrix
  tcaselect(TCAONE);
  for (uint8_t x=0; x<HOR; x++) {
    for (uint8_t y=0; y<VER/2; y++) {
      if (displayRead (x, y)) {
        ledmatrix1.drawPixel(x, y, 64);
      } else {
        ledmatrix1.drawPixel(x, y, 0);
      }
    }
  }

  // Scan the second matrix
  // Note this is oriented 180 degrees, so reverse both
  // x and y prior to setting, also of course, only using
  // the second half of the pixel array to display here.
  tcaselect(TCATWO);
  for (uint8_t x=0; x<HOR; x++) {
    for (uint8_t y=0; y<VER/2; y++) {
      if (displayRead (HOR-x-1, VER/2-1-y+VER/2)) {
        ledmatrix2.drawPixel(x, y, 64);
      } else {
        ledmatrix2.drawPixel(x, y, 0);
      }
    }
  }
}

 

Kevin

Permalink Leave a Comment

Weird Multi-I2C Bus Issues

January 11, 2019 at 8:17 pm (maker) (, , , )

This is just a quick post as a future reminder really.  I have two ScrollPhat HD Pimoroni boards that I’m using with an Arduino Nano, but as the I2C address is fixed for the boards, I’m using a TCA9548A I2C multiplexer breakout board to change I2C buses between accessing the two ScrollPhatHD boards.

But I was getting weird bus issues – sometimes only one of the boards came up, sometimes none, very occasionally, they were both fine.  I tried different channels off the TCA, swapping the boards over, I tried linking the RESET line of the TCA to the RESET line of the Arduino.  I even tried connecting the RESET line of the TCA to a digital pin and resetting the TCA manually on power up, but nothing seemed to work.

Then I saw a post somewhere about some weird I2C bus issues and one of the responses was “make sure you are calling Wire.begin();”.  I’d forgotten to put that in.

Once the code was calling Wire.begin() (only once mind), all was well.  It now powers up reliably and no resetting of the TCA is required.  All is good.

Kevin

 

Permalink 1 Comment

Pogo-pin ISP Programming Header

January 9, 2019 at 8:20 pm (maker) (, , , )

I have a batch of Arduino Nanos that have been used on projects but now don’t seem to accept a download unless I burn a new bootloader to them.  I have an excellent USBasp  ISP programmer to do that, but connecting to unpopulated ISP header pads on a nano without taking it out of a project is a bit fiddly, so I wanted a pogo-pin ISP header programmer.

But this is one of those times where I just haven’t seemed to hit on the right search terms to bring one up to buy.  So after a bit of experimenting, I’ve made my own.

Shopping list:

  • Cheap pogo-pins (I grabbed a pack of 50 from China).
  • “Dupont” crimp headers for a 3×2 header block (I got a multi-pack with a range of headers and male and female crimp inserts).
  • Your favourite ISP programmer of course.

2019-01-09 19.39.47

The idea is the solder the pogo-pins into the crimp part of the pins instead of a cable, and end up with a two-sided 3×2 header blog – pins on one side, pogo-pins on the other, as follows:

2019-01-09 19.41.142019-01-09 19.40.002019-01-09 19.55.20

The only thing to watch out for is getting the pins straight enough to make a neat 3×2 grid that will line up with header pads.  This can then be inserted in your ISP adapter header in the usual way.

2019-01-09 19.56.30

The only downside for me is that the pins are a little small still to make a perfect connection to an unpopulated set of header pads with solder holes.  But its more reliable than just poking an unsoldered 3×2 header block in the holes, which is what I was doing before.

Its a pretty simple idea, but I’ve just not seen anything like it around to buy off the shelf, or described in any kind of diy manner.  Let me know if you know of a better (cheap) solution.

Kevin

Permalink Leave a Comment