close-circle
Close
0%
0%

Toy Synthesizer

Making a rugged synthesizer toy for a teenager with developmental issues.

Similar projects worth following
close
This project is one that a former colleague brought to me. He has a teenage daughter that was unfortunately born with severe brain deficiencies who dearly likes a particular toy piano.
Trouble is, the toy piano is made for the rough and tumble of a toddler, not a ham-fisted teenager.

The plan is to develop a small synthesizer toy that can play tones and flash lights based on what buttons are being pressed. The device will be expandable to suit the needs of the situation in which it is being used.

The device at the moment is built around the ATTiny861 microcontroller which is closely related to the rather common ATTiny85. There exists ports of this firmware to the ATTiny85 and also a port that runs on a PC using libao. (By extension, should work on Linux-based single-board computers too.)

A third candidate in the AVR world would be the ATMega32U4 which is available as a through-hole module in the form of the Arduino Leonardo. This code should also work on ARM, TI MSP430 and Microchip PIC32 microcontrollers and anything else that gcc works on.

The plan is to have 8 peripheral ports (probably using DIN-8 connectors) which expose:

  • Power rails: +12V and 0V
  • A general purpose I/O line … 12V tolerant (so smoke won't be released if +12V and GPIO get crossed)
  • N-MOSFET drain output for driving lights up to ~1A
  • Microcontroller control signals for I²C networking/peripherals and ICSP programming (MOSI/MISO/SCK/nRESET)

This allows some flexibility: through the use of pull-resistors, it is possible for the microcontroller to sense what is connected on a given port by looking at the analogue voltage seen at power-up, and thus auto-detection of buttons, lights and light+button combos is possible.

Future expansion ideas:

  • Networking multiple units using an I²C "network"
  • Control from an I²C master such as a WIFI module (e.g. ESP8266) or single-board computer (Beagle Bone, Raspberry Pi, etc)
  • Reading from I²C slaves such as EEPROMs, GPIO expanders.

The idea here is a toy that can grow with the person using it. It can be used by a child (disabled or otherwise) as a toy for them to play with… then reprogrammed to create new games as they develop. The device can also be used in other projects to provide sound and light control.

To provide +12V tolerance, each channel will use a module like the following:

The design here is based on this article by Digikey on input protection. The aim here is to tolerate +12V, over-current and ESD. 8 of these, plus some tweaked ones for the I²C, MOSI and nRESET lines comprise the front line that connects the external sockets to the internal controller.

My controller has this schematic:

The microcontroller pin assignments are as follows:

  • Pin 1 (PB0, SDA/MOSI/DI): I²C SDA / ICSP MOSI
  • Pin 2 (PB1, MISO/DO): Common GPIO / ICSP MISO
  • Pin 3 (PB2, SCL/SCK): I²C SCL / ICSP SCK
  • Pin 4 (PB3, OC1B): Audio PWM output
  • Pin 7 (PB4): Audio enable
  • Pin 8 (PB5, OC1D): Light PWM output (inverted)
  • Pin 9 (PB6): GPIO Enable
  • Pin 10 (PB7, nRESET): ICSP nRESET
  • Pins 11…20 (PA0…PA7): Channel GPIOs/MOSFET control

The Port A pins connect to the inputs on two 74HC4066s and a 74HC574 edge-triggered D-latch. The light PWM connects to the output enable on the 74HC574. The GPIO Enable line controls the 74HC4066s and the 74HC574.

  • When GPIO_EN is high: the 74HC4066s connect the GPIO pins on each channel to the microcontroller so it can sense the voltage on that pin.
  • When GPIO_EN is low: the 74HC4066s go high-impedance, disconnecting the external GPIOs. The MCU is then free to assert one of the PAx lines to choose a MOSFET to turn on.
  • Once PAx has been asserted, the MCU raises GPIO_EN and sets OC1D's duty cycle, which causes the '574 to latch the selected MOSFET and to PWM it at the desired duty cycle. The '4066s connect Port A to the outside world again.

I haven't yet tested the above control scheme, but that's the theory anyway. :-)

The audio passes through a simple RC low-pass filter then is amplified by a NJR NJM2113D amplifier IC. The RC filter component values were roughly picked… I started with nominal values (1k and 100nF) with the intention of optimising later, then found that optimisation was not necessary as the performance was considered "acceptable" (there was no visible 250kHz carrier):

The synthesizer code itself is loosely modelled on the rather well regarded Commodore SID chip. I don't support the analogue filtering features of this chip, but...

Read more »

  • Trying out the toy

    Stuart Longland08/10/2017 at 10:43 0 comments

    Well, at long last we got to try the toy out.  The plan is to mount the buttons on a board so people don't have to hold them up (made to resemble jellyfish as I understand).  That said, this quick test seems to be promising.

    The teenager for whom this whole project was built, seems to be enjoying it.

  • Building synth #2

    Stuart Longland07/15/2017 at 08:41 0 comments

    So… last weekend I got to trying out the I/O modules. I rigged up wiring harnesses for all five push-buttons and their associated LED strings.

    I used CAT5e since I've got loads of it around… and ran four strands up to each button, carrying: +12V, MOSFET drain, GPIO and 0V. I ran a resistor between +12V and GPIO to pull it high, the switch NO and common connected between GPIO and 0V. The button's illumination LEDs and the LED string both connected in parallel between +12V and MOSFET drain.

    So far so good. I have just a 3-pin connection on the I/O module, carrying all but the +12V. That remaining wire I hooked to +12V directly on the input feed. Not having a 0V feed going direct to the power supply though was my mistake.

    If this happens, the 0V reference on the I/O module is open-circuit, and the zeners, meant to protect the MCU from +12V, don't do anything. So I suspect a MC14066 copped a belt of +12V by mistake!

    Not sure, but I thought I'd play it safe and build a new one anyway. I started on it earlier this week and finished it this afternoon. This time around I opted to put LEDs on the outputs of the 74HC574. No current-limiting resistors, since they're meant to be ⅛ duty cycle anyway, and if they smoke, well, who cares?

    This highlighted a glitch on the GPIO_EN signal during programming, LEDs would illuminate during MCU programming. A pull-up helps here.

    I tested using a 9V supply from my electronics kit, which has AA cells in it (somewhat stale ones) this time around. Handily, the plugs for the LED strings have LEDs in them themselves, and they work at 9V, so we can use those to see what the LED string would do.

    On the software side, I finally fixed polyphonics and a key-sticking issue. One of my I/O modules has stopped working for whatever reason, but the others are working fine, as can be seen here:

    The other issue I have to chase is some leakage on the blue and white buttons: the plugs for them are not meant to be glowing unless pressed, but you note they are glowing significantly, and get brighter when those buttons are pressed. I might have to re-visit those connections. Otherwise though, very good progress today.

  • 74HC573 replaced with '574… I/O modules built

    Stuart Longland07/02/2017 at 09:08 0 comments

    So… earlier in the week I received some 74HC574s (the right chip) to replace the 74HC573s I tried to use.

    My removal technique was not pretty, wound up just cutting the legs off the hapless 74HC573 (my earlier hack had busted a pin on it anyway) and removing it that way. Since the holes were full of solder, it was easier to just bend the pins on the '574 and surface-mount it.

    This afternoon, I gave it a try, and 'lo and behold, it worked. I even tried hooking up one of the LED strings and driving that with the MOSFET… no problems at all.

    I had only built up one of the modules at this stage, so I built another 5 on the same piece of strip board.

    The requirement is for 5 channels… this meets that and adds an extra one (the board was wide enough). For the full accompaniment and to have ICSP/networking via external connections, a second board like this could be made, omitting the MOSFETs on four of the channels to handle the ICSP control lines and reducing the capacitances/resistances to suit.

    Somewhere I have some TVS diodes for this board, but of course, they have legs, upon which they got up and ran away. Haven't resurfaced yet. I'm sure they will if I buy more though. The spare footprint on the top-left of the main board is where one TVS diode goes, the others go on the I/O board, two for each channel.

  • 74HC573, no substitute for the '574

    Stuart Longland06/11/2017 at 05:42 0 comments

    So… when laying out this board, I decided I'd swap the 74HC374 for the much nicer '574 for managing the MOSFETs. No problem, well, one minor snag, neither Jaycar nor Altronics carry the '574.

    They carry the '374… Jaycar is where I got mine originally. They also carry the very similar '573. I had intended to order some '574s for when the boards arrived, but they sort of turned up unexpectedly… so didn't get a chance.

    The fundamental difference? Apart from the '574 being edge triggered, the '573 also is active high on the logic enable pin. I had wrongly assumed it was active low.

    Naturally, I did try to hack around this fundamental difference:

    Tried to get that leg in focus, but it's difficult when the LCD of the camera is such low resolution (and the viewfinder is an even lower resolution LCD). Basically, I nibbled the leg of the IC with my sidecutters and bent it up. To the pad, I solder the gate of a 2N7000 MOSFET, bend the drain pin up to meet the now floating-in-air LE pin, and run a resistor (a 3k3) to Vcc.

    That works somewhat… it might be possible to introduce some more state machine cycles to handle the kludge… although the real fix is to use the correct part in the first place.

  • First board built

    Stuart Longland06/10/2017 at 08:58 0 comments

    So, I haven't yet tried out the MOSFET outputs, but nearly all the GPIO inputs work. I say nearly… there is one that doesn't on channel 4.

    I can test by shorting out the 0V and GPIO pins with a multimeter probe. Not sure why one channel isn't working yet, that I'll have to debug tomorrow.

    It is worth noting that the MC14066s here are older than I am if I am reading the date codes correctly. Still, they've been kept in a tube all these years, so no reason why they'd suddenly pop. More probable, I've goofed somewhere in the wiring of this.

    At worst, I should be able to de-solder the faulty chip (if that is the case) and put another one in its place… I have plenty lying around. The fact that its mate on the other side is working fine, is promising.

    The up side is this board doesn't look like a big mess of wires like the last prototype. Once I get the faulty channel sorted, I should be able to make the I/O modules that will provide the MOSFET outputs, ESD protection and switch debouncing.

    One thing I'll probably do in future: use bigger vias for my jumper wires, and actually mark on the silk screen component values and the jumper wire routes.


    Did some probing… turns out my jumper wire wasn't making good contact with the via … a dry joint. Definitely I'll make the vias bigger next time!

  • Boards have arrived

    Stuart Longland06/09/2017 at 07:33 0 comments

    So, I had a surprise delivery this morning… 10 PCBs for the new synthesizer.

    These are just two-layer affairs… with the idea being that anyone can manufacture these themselves. The top layer if made at home is done just by covering one side of a double-sided PCB with tape. The other can be done by hand with a dalo pen, using photographic methods or using toner transfer.

    One thing I did have originally, and lost when I told Kicad to delete all footprints when re-working the design, is the mounting holes in the corners, something I'll have to re-add.

    I'll have to pick up some 74HC574s (or perhaps '573s, since that's what the hobby shops sell… won't matter for this project, either will do) and get soldering this weekend.

  • Principle of operation documented

    Stuart Longland06/02/2017 at 10:42 0 comments

    Since I'm awaiting PCB manufacture (Smart Prototyping say they are onto it already… much appreciated!), I figured I'd spend some time actually documenting the theory of how this synthesizer works behind the scenes.

    The gory detail is now in the README.md in the firmware repository.

  • First working prototype

    Stuart Longland05/28/2017 at 02:07 0 comments

    So… after some cursing at me being dimwitted enough to get the amplifier around the wrong way… and luckily the amplifier is a tough little beast… I managed to get some basic functions going.

    It is supposed to be polyphonic, the synthesizer supports it, and it does actually work, but it seems my GPIO arrangement isn't picking up multiple buttons correctly.

    Ahh well, we'll get there. :-) At least it is making noises and flashing lights on cue, so in that sense, a minimum viable product has been achieved.

    Ohh, and I was able to bump the sample rate to 16kHz. 32kHz was a bit much for the little MCU though, it couldn't quite keep up.

    Code size at this point is 3.6kB… so still lots of room left. The answer might be to implement an I²C slave mode so I can interrogate it from the host.

  • Getting OC1B & OC1D to play together

    Stuart Longland05/27/2017 at 12:30 0 comments

    So… a bit of head scratching this afternoon. I had working PWM on the LEDs… which was fantastic.

    With the trade-off of LEDs being ⅛ brightness maximum, which is fine since the LED strings that I've been given for this project would make Manfred Mann proud…

    I was a little stumped with my audio PWM. I could not get a peep out of it, not via the amplifier or anything else. Tracing back, I was getting nothing out of the PWM pin. Real strange. Looked up the data sheets, couldn't see what I was doing wrong.

    My code for initialising Timer1 looked like this:

    	/* Timer 1 configuration for PWM */
    	OCR1B = 128;			/* Initial PWM value: audio */
    	OCR1D = 32;			/* Initial PWM value: light */
    	OCR1C = 255;			/* Maximum PWM value */
    	TCCR1A = (2 << COM1B0)		/* Clear OC1B on match,
    					   nOC1B not used */
    		| (1 << PWM1B);		/* Enable PWM channel B */
    	TCCR1B = (1 << CS10);		/* No prescaling, max speed */
    	TCCR1C = (3 << COM1D0)		/* Set OC1D on match,
    					   nOC1D not used */
    		| (1 << PWM1D);		/* Enable PWM channel D */
    	TCCR1D = (0 << WGM10); /* Fast PWM mode */
    It looked fine… even checked the header files to see there wasn't some cock up in the headers. Never had an issue with avr-libc, but you never know, and of course, no problem there.

    In exasperation, I swapped setting up TCCR1A and TCCR1C. Bingo, I had PWM both channels. Why? Turns out there are some bits in TCCR1C that shadow TCCR1A, and I was inadvertently setting those back to 0 when I set up TCCR1C. So my code now:

    	/* Timer 1 configuration for PWM */
    	OCR1C = 255;			/* Maximum PWM value */
    	TC1H = 0;			/* Reset counter high bits */
    	TCNT1 = 0;			/* Reset counter low bits */
    	OCR1A = 0;			/* Initial PWM value: spare */
    	OCR1B = 127;			/* Initial PWM value: audio */
    	OCR1D = 127;			/* Initial PWM value: light */
    	TCCR1A = (1 << PWM1B);		/*
    					 * Clear TCCR1A except for PWM1B,
    					 * we'll configure OC1B
    					 * via the shadow bits in TCCR1C
    					 */
    	TCCR1B = (1 << CS10);		/* No prescaling, max speed */
    	TCCR1C = (2 << COM1B0S)		/* Clear OC1B on match,
    					   nOC1B not used */
    		| (3 << COM1D0)		/* Set OC1D on match,
    					   nOC1D not used */
    		| (1 << PWM1D);		/* Enable PWM channel D */
    	TCCR1D = (0 << WGM10);		/* Fast PWM mode */
    	TCCR1E = 0;			/* Not used: PWM6 mode */
    We still need to turn PWM1B on via TCCR1A… but we set the output control mode via TCCR1C to avoid clobbering our settings.

    Having fixed that, I now have a second problem, in my dead-bugging of the amp, I got my left and right arse-about, which would explain why my amp is making no noise. That'll be a tomorrow job methinks, at 22:30 UTC+10:00 it is too dark to work on PCBs. I'll just keep myself amused looking at the waveform on the oscilloscope.

  • PWM Outputs work

    Stuart Longland05/27/2017 at 04:31 0 comments

    So, I've done some tweaks to the prototype… namely fixing some wire assignments. I also had to drop my 1k resistor on the input to a 100R as the voltage drop of the 1k was too high.

    At the moment, I am seeing ~3V at the MCU, which is good enough.

    Beneath the afro of wires, is the prototype.

    … and this is the PWM LED control in action (animated GIF). So PWMing the output enable of a 74LS374 works, and doing the same on a 74HC574 should too.

View all 11 project logs

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates