Korg PolySix Tuning – The Long Story

The tuning of a Korg PolySix is mostly a tedious process. Let’s go in-depth to make it even worse. The tuning process described here is normally not necessary, but if you have replaced some components on the Voice PCB this might be your last resort.

Korg PolySix (with KiwiSix CPU board, your LED states may be different)

Sources of information

  • The PolySix Service Manual. There is some important information in there, like the fact that the PolySix is not speced to be able to tune in the highest octave. But generally the tuning instructions in the service manual should be read, understood and avoided.
  • The KiwiSix manual, section 5) “PolySix Adjustments”, paragraph 9) “Voice Pitch Tuning”. It has helped me out many times. (You don’t need to have the KiwiSix upgrade installed.)
  • This page. It’s for when you can’t get it right with the KiwiSix procedure.
The voice PCB, KLM-366

Step-by-Step Instructions

Front Panel Preparations

  • Set Waveform to Saw
  • Tune Knob = Center
  • Modulation Level = 0
  • Bend Intensity = 0
  • Move Modulation wheel to 0
  • Move Pitch Bend wheel to the Center detent

Voice Board Preparations

  • Everything will happen on the voice PCB (KLM-366). Pull the slide switch between VR1 and VR2 towards the rear of the PolySix (away from connector CN12). This is the ‘normal’ tuning position. The other position is for stretch tuning.

These “global” trimmers will affect all voices

  • VR1 (Adj Center)
  • VR2 (Tune High)
  • VR3 (Tune Low)
  • VR14 (D#4-E4 Adj)
  • VR15 (Tune Mid)

Per-voice trimmers

  • VR10 (Tune Low) * 6
  • VR11 (Tune High) * 6

Note: In early production models
VR14 is not present 
VR15 (Tune Mid) is called VR1 and sits on the KLM-396 daughter board

Trimmer positions

Tuning Procedure, Global + Voice 0

First adjust global trimmers together with Voice 0. Save Voices 1-5 for later. Use the LEDs on the Voice PCB to identify which voice is currently playing.

a) Set Octave to 4′ (on the front panel)

b) Hit C5 (second top C) until the LED for Voice 0 is lit. Adjust VR11 to obtain C7 0 cents.
(If VR11 is far off from center: adjust VR2 (Global) Tune High a bit and try again)

c) Play C2 (second lowest C) and adjust VR1 to obtain 0 cents for Voice 0.

Repeat (b – c) until C2 and C5 are in tune for Voice 0

d) Play C3 and adjust VR15 to obtain 0 cents (It might not be possible right now. If not, do your best)

e) Play D#4 and E4 and adjust VR14 until both are spot on. (It might not be possible right now.)

Repeat (d – e) to get C3 and D#4-E4 a bit closer to correct pitch

Repeat (a – e) until C5, C2 and C3 are good. Then go to (f).
If you can’t match C2 and C3, i.e. if step (c) and (d) seem to counteract each other, please also go to (f).

f) Set Octave to 16‘ and play C2. Adjust VR3 (Tune Low) for 0 cents. This can help with steps (c) to (d). Try to leave VR10 close to center position for Voice 0.

Repeat (a – f) until Voice 0 is in tune

Voices 1 – 5

Generally, from here on, you want to avoid changing the “global trimmers” VR1, VR2, VR3, VR14 and VR15.

h) Set Octave to 4′
Play C5 and adjust VR11 for Voice 1 – 5

i) Set Octave to 16’
Play C2 and adjust VR10 for Voice 1 – 5

Repeat (h – i) until Voice 1 – 5 are in perfect tune

Done!

Technical Notes

If you are unable to tune a PolySix, there are some components that fail more often than others in the “auto-tune” and expo converter section.

  • 4051 multiplexers are always suspects
  • The opto-coupler (aka “Vactrol”) HTV P1501, cannot be sourced nowadays, but might be replaced with VTL5C9 or NSL32-SR3. Due to differencies between specs, but also between individual optocouplers, other alterations may be needed in the PolySix “auto-tune” circuit. If VR15 (Tune Mid) and VR1 (Adj Center) counteract each other, so that C3 stays too sharp, and you finally hit bottom while turning VR15 clockwise, then you may need to decrease the value of R216 a bit.
  • Sometimes IC17 – 19 need to be replaced. If you change IC17 and IC18 to TL072, instead of the less common JRC072, there’s a resistor change you need to perform, specified in the KLM-266 schematic, in the service manual.

 

Arduino FastLED Library – a visual reference for the predefined colors

The FastLED Library for Arduino and other microcontrollers is used for controlling LED-strips with one to hundreds of individually addressable RGB LEDs. Here is a visual reference to the colors that are pre-defined within FastLED. In C++ they can be accessed by name, like this:

CRGB my_color; // Define a variable of type CRGB
my_color = CRGB::AliceBlue; // Variable now contains AliceBlue

The colors in this list appear in the same order as in the FastLED struct that defines them.

The struct itself looks like this:

HTMLColorCode { 
AliceBlue = 0xF0F8FF, Amethyst = 0x9966CC, AntiqueWhite = 0xFAEBD7, Aqua = 0x00FFFF, Aquamarine = 0x7FFFD4, Azure = 0xF0FFFF, Beige = 0xF5F5DC, Bisque = 0xFFE4C4, Black = 0x000000, BlanchedAlmond = 0xFFEBCD, Blue = 0x0000FF, BlueViolet = 0x8A2BE2, Brown = 0xA52A2A, BurlyWood = 0xDEB887, CadetBlue = 0x5F9EA0, Chartreuse = 0x7FFF00, Chocolate = 0xD2691E, Coral = 0xFF7F50, CornflowerBlue = 0x6495ED, Cornsilk = 0xFFF8DC, Crimson = 0xDC143C, Cyan = 0x00FFFF, DarkBlue = 0x00008B, DarkCyan = 0x008B8B, DarkGoldenrod = 0xB8860B, DarkGray = 0xA9A9A9, DarkGrey = 0xA9A9A9, DarkGreen = 0x006400, DarkKhaki = 0xBDB76B, DarkMagenta = 0x8B008B, DarkOliveGreen = 0x556B2F, DarkOrange = 0xFF8C00, DarkOrchid = 0x9932CC, DarkRed = 0x8B0000, DarkSalmon = 0xE9967A, DarkSeaGreen = 0x8FBC8F, DarkSlateBlue = 0x483D8B, DarkSlateGray = 0x2F4F4F, DarkSlateGrey = 0x2F4F4F, DarkTurquoise = 0x00CED1, DarkViolet = 0x9400D3, DeepPink = 0xFF1493, DeepSkyBlue = 0x00BFFF, DimGray = 0x696969, DimGrey = 0x696969, DodgerBlue = 0x1E90FF, FireBrick = 0xB22222, FloralWhite = 0xFFFAF0, ForestGreen = 0x228B22, Fuchsia = 0xFF00FF, Gainsboro = 0xDCDCDC, GhostWhite = 0xF8F8FF, Gold = 0xFFD700, Goldenrod = 0xDAA520, Gray = 0x808080, Grey = 0x808080, Green = 0x008000, GreenYellow = 0xADFF2F, Honeydew = 0xF0FFF0, HotPink = 0xFF69B4, IndianRed = 0xCD5C5C, Indigo = 0x4B0082, Ivory = 0xFFFFF0, Khaki = 0xF0E68C, Lavender = 0xE6E6FA, LavenderBlush = 0xFFF0F5, LawnGreen = 0x7CFC00, LemonChiffon = 0xFFFACD, LightBlue = 0xADD8E6, LightCoral = 0xF08080, LightCyan = 0xE0FFFF, LightGoldenrodYellow = 0xFAFAD2, LightGreen = 0x90EE90, LightGrey = 0xD3D3D3, LightPink = 0xFFB6C1, LightSalmon = 0xFFA07A, LightSeaGreen = 0x20B2AA, LightSkyBlue = 0x87CEFA, LightSlateGray = 0x778899, LightSlateGrey = 0x778899, LightSteelBlue = 0xB0C4DE, LightYellow = 0xFFFFE0, Lime = 0x00FF00, LimeGreen = 0x32CD32, Linen = 0xFAF0E6, Magenta = 0xFF00FF, Maroon = 0x800000, MediumAquamarine = 0x66CDAA, MediumBlue = 0x0000CD, MediumOrchid = 0xBA55D3, MediumPurple = 0x9370DB, MediumSeaGreen = 0x3CB371, MediumSlateBlue = 0x7B68EE, MediumSpringGreen = 0x00FA9A, MediumTurquoise = 0x48D1CC, MediumVioletRed = 0xC71585, MidnightBlue = 0x191970, MintCream = 0xF5FFFA, MistyRose = 0xFFE4E1, Moccasin = 0xFFE4B5, NavajoWhite = 0xFFDEAD, Navy = 0x000080, OldLace = 0xFDF5E6, Olive = 0x808000, OliveDrab = 0x6B8E23, Orange = 0xFFA500, OrangeRed = 0xFF4500, Orchid = 0xDA70D6, PaleGoldenrod = 0xEEE8AA, PaleGreen = 0x98FB98, PaleTurquoise = 0xAFEEEE, PaleVioletRed = 0xDB7093, PapayaWhip = 0xFFEFD5, PeachPuff = 0xFFDAB9, Peru = 0xCD853F, Pink = 0xFFC0CB, Plaid = 0xCC5533, Plum = 0xDDA0DD, PowderBlue = 0xB0E0E6, Purple = 0x800080, Red = 0xFF0000, RosyBrown = 0xBC8F8F, RoyalBlue = 0x4169E1, SaddleBrown = 0x8B4513, Salmon = 0xFA8072, SandyBrown = 0xF4A460, SeaGreen = 0x2E8B57, Seashell = 0xFFF5EE, Sienna = 0xA0522D, Silver = 0xC0C0C0, SkyBlue = 0x87CEEB, SlateBlue = 0x6A5ACD, SlateGray = 0x708090, SlateGrey = 0x708090, Snow = 0xFFFAFA, SpringGreen = 0x00FF7F, SteelBlue = 0x4682B4, Tan = 0xD2B48C, Teal = 0x008080, Thistle = 0xD8BFD8, Tomato = 0xFF6347, Turquoise = 0x40E0D0, Violet = 0xEE82EE, Wheat = 0xF5DEB3, White = 0xFFFFFF, WhiteSmoke = 0xF5F5F5, Yellow = 0xFFFF00, YellowGreen = 0x9ACD32, FairyLight = 0xFFE42D, FairyLightNCC = 0xFF9D2A
}

Ursa Major Space Station SST-282, 82S123 replacement

How to make a replacement for the 82S123 ROM chip (ADS-1 board – U19) in Ursa Major Space Station SST-282, using an 22v10 Programmable Logic chip and a cheap EPROM programmer.

I used Atmel ATF22v10CQZ-20PU and the common TL866iiPlus.

This is not a step-by-step guide, you are expected to know how to use an EPROM programmer.

Main SST-282 main image
Two Space Stations in for service, one with a problematic 82S123

What is the N82S123N chip

The Space Station doesn’t have a processor, but you can still select different reverb-, filter- and delay algorithms. This is achieved with hardware buttons that make the 82S123 IC output various control signals to the rest of the machine.

Two M82S123N chips from the SST-282
82S123 from the two Space Stations above

The 82S123 is not an ordinary EPROM, it’s a bipolar TTL PROM. It is way faster than EPROM, with response times in the nanoseconds. You can get them NOS on eBay. The problem is that an EPROM programmer that supports this type of chip is expensive.

I haven’t verified this, but these chips should be direct replacements for the 82S123:
7112, 27S19, 6331-1N, 74S288, 18S030, 7603

The ATF22v10C Programmable Logic IC

Atmel F22v10CQZ-20PU and little brother F16v8BQL-15PU

The ATF22v10 is a Programmable Logic chip, made by Atmel. Other brands are sometimes called PAL chips. ATF / PALs are much more flexible than EPROMS, mainly because you can run small programs on them, so they behave differently depending on signals present on the input pins. They are also very fast, and that’s why they are fit to replace an 82S123.

So in short, I needed the 22v10 to output one of 32 numbers, depending on the state of its input pins – just like a small EPROM.

Research

Luckily I found someone that made a 82S123 replacement using the GAL22v10D, which is “practically the same” chip: REPROGRAMMABLE 82S123. Beware though that not all EPROM programmers and ATF / PAL / GAL chips are compatible.

So I read a bit of documentation on 22v10, as well as the programming language (CUPL Compiler for Universal Programmable Logic) and tool (WinCUPL)

Hardware adapter

22v10 is a 24-pin chip, whereas 82S123 is only 16-pin, so an adapter is needed. Please refer to this site for detailed information: REPROGRAMMABLE 82S123

My version looks like this

82S123 socket to 22v10 IC adapter top
82S123 socket to 22v10 IC adapter bottom

Programming the Space Station data to 22v10

You need an EPROM programmer that is compatible with the 22v10 brand that you have

Done

Ursa Major Space Station with the new ATF22v10C added

Addendum

“Why not use the smaller 16v8 PAL instead? It’s smaller but it has enough pins…”

Well, if you try to compile any code that contains a 32 byte ROM table and the necessary pin bindings in WinCUPL it’s going to fail. WinCUPL even outputs a nice Word document that shows exactly where the resources are exhausted.

The differences between Roland Juno-106 and MKS-7

The Roland MKS-7, a “6 note polyphonic / mono bass / TR707 drum sound” module

The Roland MKS-7 was allegedly intended for MIDI-file playback and karaoke, thus being a consumer market product. The voicing hardware is similar, but not identical, to the Juno-106.

Roland Juno-106 patch-making controls

Background

A Roland MKS-7 could be considered a more affordable, yet in some respects more capable, version of the Juno-106.

Juno-106 advantages

  • Sliders and buttons for every patch parameter
  • User patch storage
  • No restrictions on how to use the 6 voices – simple

MKS-7 advantages

  • Velocity control of filter and VCA
  • Lower second hand price than Juno-106
  • More voices – 6 poly voices, plus one dedicated bass voice, plus drum sounds
  • Multitimbrality, to some extent

Here are the parameter differences between the two. The tables are from the MKS-7 service manual, with Juno-106 specifics noted in orange. My notes follow after the image.

Differences, not mentioning Juno-106 keys, knobs and sliders…

So what’s specific for the MKS-7?

  • Dynamic select (aka velocity control) – Yeah baby! This is a big thing. The Juno-106 lack of velocity sensitivity is possibly its biggest weakness.
  • Sub OSC level in 4 steps instead of slider – Seriously, this wouldn’t make much of a difference.
  • High Pass Filter is ON/OFF instead of a slider – Personally I don’t think this damages patch creation much.
  • Chorus, only one mode – This is a problem. A lot of the dreamy character of Juno-106 stems from Chorus II.
  • Noise – Noise is only available on 2 of the 6 voices, and even so it’s only available at full volume or nothing. Some people like to add grit to a pad sound with a little noise.

The Bass voice

The bass voice differs from the ordinary voices in many respects. It has no modulation at all except envelope. It cannot have saw and pulse waveforms at the same time. No noise, no inverse envelope, no HPF etc. On the plus side, the Bass has an analog envelope. This is important because it’s exponential, so has more punch with short attack- and decay settings. All things considered, this bass is a lot more trimmed-down than any bass synth, like SH-101 or MC-202. Since it lacks velocity sensitivity I dare say it’s even more basic than the TB-303 sound engine which sports accent and slide controls. Still, it’s a rock solid bass, and a lot of people like it a lot.

Creating patches and saving them

The MKS-7 comes with 100 chord / melody presets and 20 bass presets. A software SysEx editor, or DAW plugin, can be used to edit the MKS-7 parameters. But everybody ideally wants hardware sliders and buttons. You could get a Stereoping Juno-106 programmer or a Behringer BCR for that. But doing so, you still can’t save your patches in the MKS-7. So you will have to save your SysEx patch in your sequencer, in a SysEx librarian, or within your programmer if it allows that (Behringer BCR does not).

Conclusion

Using the MKS-7 to get a Juno-106 is just too much hassle. The only things making me consider it is the price difference and that the MKS is velocity sensitive. I’ll stay with the JU-06.

Arp Sequencer 1621 / 1601 Button Debounce

Arp Sequencer 1621 / 1601. The changes between versions are only cosmetic.

While servicing an Arp Sequencer 1621, I noticed that the three button switches were in a bad shape. One button press would produce anything from one to six signal changes.

These switches can’t be sourced nowadays. The switches are glued together from factory so they can’t be opened.

One possible fix would be to fit some type of modern (long slew) replacement switch inside. You would probably need to design an individual adapter PCB to make it fit the footprint on the 1621 PCB, and also 3D-print an adapter to stick the white button caps back on. However, there’s no guarantee that any other switch will work flawlessly even if it’s new. All electromechanical switches bounce.

I tried removing and washing the switches with ultrasound, warm water and dishwashing detergent. That helped to some extent, but they still exhibited double-triggering and trig on release.

Top traces show how a button press generates bounces

Using the original switches

I decided to hardware debounce the switches, using RC filters. I had the following design goals, in addition to making it work:

  • Don’t change any components on the 1621 PCB
  • Make it visually clear to anyone what my addition does
  • Stick my PCB to the main PCB, not the bottom of the unit, to keep it simple to open and service

The lower traces in the images above show the RC filtered signal, with the third image showing an extreme case, which I’ve not been able to replicate again. The RC filter will introduce a delay from button press to state change, but it can probably be kept under 10 ms. It depends on how badly degenerated the switches are, their original construction and possibly in what manner they will be hit in actual use: A more firm hit will probably make a shorter period of contact noise (?)

Here some Internet programmer’s well designed RC debounce circuit. Button closing will make pin 1 of U1 see a smooth signal falling towards LOW. Opening the button makes pin 1 see a signal rising to HIGH. The fall and rise rates are defined by R2 * C1 and R1 * C1 respectively.

The diode, while not necessary, makes the charge rate (going towards HIGH) of the capacitor depend only on R1, not R1 + R2.

U1 is an inverter, so the resulting voltage state at pin 2 will be the opposite of pin 1.

https://mayaposch.wordpress.com/2018/06/26/designing-an-rc-debounce-circuit/

CD40106B inverter

The 40106 is a 20 volt tolerant inverter with Schmitt-trigger. Logic levels in the 1621 are +15 and 0 volt. The Schmitt-trigger handles noise and slowly rising or falling voltages well and is a good companion to the RC filter for debouncing.

Schmitt-trigger (noisy) input and output

There is no technical advantage of inverting the output signal, but the inverter isolates the switch and RC network from from the rest of the circuitry. This can be important when fitting a debounce circuit to an existing system, otherwise you’re likely to unintentionally create voltage dividers that will affect the performance of the debounce circuit, and possibly offset the resulting signal.

Upper trace: RC filtered signal. Lower trace: Filtered signal after inverter + Schmitt-trigger

Special considerations and adjustments are needed when fitting something like debounce to an existing system. In the 1621 the signals from the switches are later combined with other signals from the input jacks. The original switch construction doesn’t have a HIGH and a LOW state, it has LOW state and UNCONNECTED (in case of the “Start / Stop” and “Reset” switches), and HIGH state and UNCONNECTED (for the Step switch).

Start/Stop Example

When “Start/Stop” switch is UNCONNECTED there’s a weak pull-up that keeps the signal line in HIGH state. This pull-up is weak enough for another connected signal (via External input jack) to pull the line down to LOW if needed.

1601 schematic, the “Start/Stop” input signal and switch

The RC scheme however, can’t have an UNCONNECTED state, only HIGH, LOW or intermediate values. When the debounced switch is off it could therefore affect the “Start/Stop” signal line, and hinder other signals from forcing it LOW. To remedy that, I added D1 and D2 in the following image.

Implementation

The schematic only shows two circuits. That’s because “Reset” and “Start/Stop” use the same top design (except for one resistor value). “Step” uses the bottom design.

When I tested everything out, I realized that I had created an unwanted behavior in the 1621. Every time I turned the power on, it jumped a number of steps into the sequence, as if the “Step” button had been pressed a few times after startup. That’s natural, since in practice I had delayed the switches by a couple of ms, not only when pressed, but also on startup. I changed R3 to 22k so it would appear to the 1621 as if “Reset” button was pressed a few ms after the other buttons, taking the sequencer back to step 1.

Breadboard test
Transferring
All paths to switches are cut on the PCB, wires connect them to the debounce board
There’s a piece of acrylic between the PCBs to keep the distance
Keeping related wires together

Conclusion

This Arp Sequencer 1621 works as it was intended again. The reaction to button-presses is fast enough, and feels solid and reliable.

I could have done this with a lot fewer wires if I had been more creative with where I cut the PCB paths, in combination with inverting signals once more to get back to uninverted state. But then it would have been much harder to follow the signal flow for the next service technician.

I taped a printout of the schematic, and added a link to this site on the inside of the unit.

Korg Lambda ES-50 Tuning Instructions

Disclaimer: There may be a better way to tune the Korg Lambda. My method is a bit “hit and miss”. Still it took less than five minutes to accomplish.

Korg Lambda ES-50 string machine

Background

The Lambda is not a VCO->Filter->VCA synthesizer, it’s constructed lika an organ / string machine. The tuning procedure is different and often simpler on an organ than on a synthesizer. Maybe that’s why, when searching the web for tuning info, I came across statements like these:

Actually, I don’t think the Lambda stringer has got any trimmers to do the tuning, except the little pot on the chorus circuit board, that tunes the LFO rate range of the effect.

Well, it’s very rare that such string machines would require tuning becuase they use different technology than synthesizers.

The knobs positions on the front

Tuning the Korg Lambda

Turn all instrument buttons off, except BRASS. Set Chorus Phase Off. Set all three TUNE knobs: Total Tune, Tune A and Tune B to center position. Vibrato Off. Get a very small screwdriver.

It’s likely that the Lambda sounds very dissonant in this state. If it does, adjust VR Tune A and VR Tune B until both LEDs are steadily lit. Now it doesn’t sound dissonant anymore, but it’s probably still out of tune.

The trimmers (VR). Their positions match the positions of the knobs on the front.

Now the guessing starts

  1. Adjust VR Total Tune right for sharper tuning, left for flatter. You will notice that the sound also gets dissonant, so you can’t really hear if you hav hit the right pitch.
  2. Adjust VR Tune A and VR Tune B until both LEDs are steadily lit again. Now you can hear the actual pitch of the instrument.
  3. It’s likely that you will realize you turned VR Total Tune too far, or not far enough. Repeat steps 1-2.

Soon you get familiar with how much you need to adjust VR Total Tune in order to raise or lower the pitch by a few cents.

That’s it

Korg Poly-61 – Changing the NiCd to a Litium Battery

The Korg Poly-61, DCO analog synthesizer

The Korg Poly-61 has the same type of battery as the Korg Polysix, the type that creates the infamous battery-leak disasters. Here’s how to modify the Poly-61 for a standard litium coin-cell battery. The coin-cell is seated in a battery holder, so can easily be changed by the owner, without soldering.

Background

The original batteries in Korg Poly-61 (and Polysix) are charged at any time the synth is on. The coin-cell litium battery is not rechargeable. If you would just insert a litium battery in the circuit, the battery would break and possibly catch fire or explode. So you need to stop the current flow from the PSU to the battery.

Also don’t replace the NiCd battery with a new rechargeable battery such as Lithium-Ion or NiMh. The Poly-61 charging method is not suited for those, and they will break.

Old Crow (RIP) has info on battery modification and battery leak repair for the Polysix. I Adapted it for Poly-61.

Changes

Remove this

  • Old battery
  • Resistor R70 (replace with diode)
  • Capacitor C29

Add this

  • Diode, eg 1N4148 (Please watch the direction, see schematic)
  • Coin cell battery holder
The changes
PCB positions of R70 and C29

PPG 1020 Tuning Instructions

Disclaimer: I have no idea. Maybe this can be done better. But here’s my best shot.

Background

There is not much technical information around about this very rare synth. In order to figure out how to tune it, I had to remove the front plate which is a lot of work. This article is an attempt to save you from that.

The specimen I got to the workshop was close to a prototype. I don’t if the numerous modifications and extra installments were factory-made, or done later. The PSU is part of the main PCB, except for the transformer, so it’s not immediately apparent what is what. There is trimmer for +12 volt, and it was easy to get it very exact. There’s no trimmer for -12 however, and it was around -10.5 volts, don’t know if that’s within specs, but it seems a bit far off.

Thanks to Stefan Huebner I knew that the oscillator control voltage is part digital and part analog: The octave is selected digitally, and the voltages within an octave are analog. This means that if you notice that F1 key, for example, is off by 20 cents, then every F is going to be off by 20 cents. But some other note, say all D keys, could be in tune.

The problem

The two oscillators had the same pitch on some notes, but where off by almost a quarter-note on others. The behavior repeated for each octave. Which exact notes where in tune could be adjusted with the OSC B PITCH knob.

Some tuning info

On an analog synthesizer, there’s traditionally one Offset trimmer (VR), and one Scale VR for the Lin-to-Exponential Converter for an oscillator. The circuit assumes that the input is a fairly exact linear 1 v / octave voltage. I found Scale VR and Offset VR for OSC A, and a Scale VR for OSC B.

Part of the PCB

It was not possible to adjust the OSC A Offset enough to get it in tune, probably due to one of these reasons:

  • The negative supply was only -10.5 v
  • Some modification to the PCB has broken the voltage supplied to the lin-exp converter
  • I misunderstood how the TUNE knob is supposed to work. Maybe it’s more like the Sequential Pro-One, where the oscillator is in tune when the knob is at zero. I assumed that the “neutral” setting would be in the middle of the knob range, which is 5. Otherwise it would not be possible for the user to tune the synth if it is too sharp.

Tuning the PPG 1020

Oscillator A

OSCILLATOR CONTROLLER / TUNE = 5, turn down OSC B, all modulation off, OUTPUT I LEVEL = 0, OUTPUT II LEVEL = 10

  1. Press any G key, for example G2
  2. Use OSC A Offset VR to get correct pitch for G2. If not possible, adjust the OSCILLATOR CONTROLLER / TUNE knob
  3. Press G#2
  4. Use OSC A Scale VR to get correct pitch for G#2
  5. Repeat 1-4 until both G2 and G#2 are in tune

This is the way to get the best pitch overall. On my synth about half of the keys within the octave were in perfect pitch, while others were flat or sharp by up to 10 cents.

Oscillator B

Turn up OSB B in the mixer. You’ll hear some beating between OSC A and OSC B when playing notes.

  1. Press G2
  2. Use OSCILLATOR B; PITCH knob to get zero beating
  3. Press G#2
  4. Use OSC B Scale VR to get zero beating
  5. Repeat 1-4 until there’s no beating

You will notice that even if one key, say D#, is off by +8 cents, it’s exactly the same for both oscillators, so at least there’s no beating.

That’s it! Thanks for listening

Roland TR-505 – A Better Mod for Individual Outputs

Descriptions of Individual Audio Outputs modifications for the Roland TR-505 have been around for a while. I searched the web for sources that describe how to do the mod:

There are many sources talking about having it done, without explaining how:

The problem

However, the modifications that are described share one problem: They don’t handle Cymbals and Open HiHat very well. That is because the signal is tapped too early in the output summing circuitry, before the volume envelope is applied. Citing circuit benders’ description of their mod:

“Longer sounds such as the crash and hats consist of a compressed sample, with a primitive envelope applied to it so it sounds vaguely realistic. As the outputs have to be sourced in the circuit before the envelope is applied, some sounds will not be identical to the main mix outputs.”

Image from masutopedals.wordpress.com/

How to do it better

To sort it out, you need to tap audio from (LT MT HT TB) (CC RC) and (CH OH) after transistors Q6, Q7 and Q8 respectively, because the transistors apply the volume envelope to the audio signals. However the signal can’t be taken directly from the emitter of the transistor, because it’s is very weak at this point, and you will introduce noise, hum and instability. Instead, we take it after the buffers / amplifiers IC16 and IC15 respectively.

Red shows the standard 505 mods, green shows my modification spots

You will use the standard mod spots for (HCP RIM) (LCB HCB) (SD) (LCG HCG) and (BD), and the green ones for (LT MT HT TB) (CC RC) and (CH OH). I used breaking 3.5 mm jacks, so the sound is removed from the R / L mix when a cable is inserted in the individual output jack.

What you lose

You are going to lose the predefined, fixed panning that some of the sounds in the TR-505 have. But you will have all sounds on individual mixer channels to pan, equalize and add effects.

Also, the volume levels of the individual outputs may not be exactly the same as on the R / L outs.

Roland CR-8000 BD / SD Mod

This drum machine from 1981 is a close relative of Roland CR-78 and TR-808. It has a couple shortcomings, such as no user editable sounds, a Snare Drum with a lot of tone (what is called “Snappy” on 808) but a lack of noise / high frequency content. It sounds more like a tom. Also the Hand Clap is low volume, at least on this specimen.

This CR-8000 was modified for individual audio outputs for each instrument group, a louder Hand Clap, as well as couple of potentiometers for Bass Drum and Snare Drum tuning. The BD now has two controls: Pitch and Decay, the SD has two controls: Pitch of the “snappy” portion, and Noise level.



The BD and Clap modifications are taken directly from gumielectronic. The exact changes with component values are listed further down in this article.

When servicing or modifing synths I try to conform to Hippocrates’ oath for medical doctors: “First, do no harm”. So I made a break-out box, instead of drilling holes in the CR-8000 exterior. Also I left the original parts in place on the PCB where possible, should someone want to reverse this mod in the future.

The break-out box sticks to the metal back plate of  the CR-8000 with neodyme magnets. The wires are routed through existing vent holes in the back.

The following list is an excerpt from gumielectronics’ extensive CR-8000 modifications. The red markings are the ones I chose to use (since there was limited space on the break-out box) along with my component selections. The Snare Drum are my own changes, as some of gumielectronics’ suggested changes didn’t make that much difference. C47 is Snappy Pitch, the changes after Q7 is the SD Noise portion boost.

Below are Snare Drum specifics. The exact original SD sound isn’t available anymore, it now has a bit more noise content.

Here are a couple of images of the PCB and break-out box internals:

Bass Drum (green wire and some resistors) and Snare Drum Snappy (yellow wire bridging R34):

Snare Drum Noise Boost (red wires) and Snappy pitch (blue wires):

Individual outputs:

Tidying up a bit:


Caveats

Individual Outputs: The CR-8000 was not designed to have separate outs to begin with. Some things are not possible to do the way you’d want because of this. The Clap for example, is lower at the individual output than it is in the main mix. (Just mix it up a bit with the knob, or on your mixer). Also the accent effects are not applied to the individual outs, so in some cases the Main out instruments will sound beefier than the indy versions. This is often not a problem, since you can either do a lot to beef the sound up on an individual mixer strip, or you can leave that particular instrument on the main mix out and direct everything else to individual outputs.

BD Decay: The Bass Drum will not have the oomph of the TR-808, maybe because of a shorter trig pulse or some other volume envelope characteristic that might be different.

SD Decay: Decay of the Snare Drum is hard to modify, unlike the Bass Drum. The mod point called “decay” in gumi’s description doesn’t change the overall decay of the instrument, only the length of the Snappy portion within the (very short) total length of the Snare Drum, and this change is hard to hear to be honest. I think it would need a longer trig pulse to make the Snare longer, but I haven’t tested this idea.

Conclusion

I believe the changes described here are a significant improvement to the CR-8000.

 

Toaster with web server

Arduino files download: Sonoff_toaster_timer

First install ESP8266 support for Arduino IDE. Follow these instructions:
https://github.com/esp8266/Arduino

Reprogram Sonoff Smart Switch with Web Server. I didn’t use this in the end, but learned the basics:
https://randomnerdtutorials.com/reprogram-sonoff-smart-switch-with-web-server/

ESP8266 ajax – update part of web page without refreshing. The main source for my toaster’s html page:
https://circuits4you.com/2018/02/04/esp8266-ajax-update-part-of-web-page-without-refreshing/

ESP8266 Timer / ticker examples. Helps keeping track of time / elapsed seconds:
https://circuits4you.com/2018/01/02/esp8266-timer-ticker-example/

Background

My toaster had a mechanical problem: It didn’t release the bread, or turn off, when time was up – Instead it continued toasting forever. This is my second toaster of the same type that breaks. It’s obviously not reliable, but it does take long slices of bread

So I had the idea to control the power supplied to the toaster, instead of trying to fix its mechanics.

I got a couple of Sonoff WiFi relay switches off eBay, hoping to automate a few things at home. I soon realised it would not be possible because of the way they are programmed to work: They use your WiFi to connect to a global server, where you have used their “EWeLink” app to set up an on / off schedule for the switches. That scheme would be useless for my purposes for many reasons:

  • When I got the switches (Christmas 2017) there was a global Sonoff hype. The server was unreachable, probably due to heavy traffic.
  • You need internet to use the Sonoff. Of course I wanted to be able to make a toast even if my ISP was having problems that morning.
  • I suspect that if you would turn on a switch and then loose connection to the server, it would stay on forever. This would cause any inserted bread to catch fire.
  • The scheduling control was too unprecise. You can set events to minutes at best, but I needed second’s granularity.
  • There was no way (at least not back in 2017) to turn a switch on, and have it turn off after a set time interval. You could only turn it on (maybe 07.23) and then set it to turn off at another time stroke (07.25 or so).

The Project

I already nourished a long-standing toast dream: To be able to sequence the toasting like this: Toast-Pause-Toast-Stop. I had previously noticed that the toast quality was increased significantly when I did this manually – The slices didn’t get dry on the outside and wet on the inside. Instead they became crisp all the way through.

I also wanted presets for different types of bread, or for users with various demands.

The Sonoff serving a local web page

The Sonoff contains an ESP8266 processor that does most of the work. Most importantly ESP8266 has WiFi capabilities, which is why it’s used in many Internet of Things-applications. It’s possible to run a web server on the ESP8266, and have it serve a web page with a user interface for the Sonoff on / off switching. So in my case it serves a HTML / Javascript page with five buttons and a progress bar. The buttons select one of three toast sequence programs, a one-shot 30 seconds toast program or stop. The shortest toast program is for white bread that is a bit dry, the longest is for dark bread that is frozen.

The Stop button doesn’t fit on my medieval iPhone 5 screen

New firmware, Arduino, randomnerdtutorials.com

To upload firmware to the ESP8266. I used Arduino IDE 1.8.1 and a USB-Serial TTL converter. I followed these instructions for wiring: https://randomnerdtutorials.com/reprogram-sonoff-smart-switch-with-web-server/

Sorry, the power cord just popped off

There was also info on what libraries needed to be installed, how to set up an ESP web server, connect to Wifi and more. A good place to get started.

Maybe not randomnerdtutorials, after all

I soon realized that the code on randomnerdtutorials would be dangerous for this project. It works something like this: When you click a button on the web page, a new page is loaded. Appended to the URL is the name of the button that you clicked. This is a common way to pass data between html pages. The problem is that when the toast program is finished, it’s quite possible that you still have this page (with the button name) loaded in your web browser. Which means that if you reload the page (which can happen automatically in many situations, ie on a computer restart) the toaster will start again.

AJAX, circuits4you.com

Then I found this page: https://circuits4you.com/2018/02/04/esp8266-ajax-update-part-of-web-page-without-refreshing/ that demonstrates using AJAX XMLHttpRequest techniques to do calls without reloading the page. It was a better fit for my needs in many ways:

  • URL doesn’t change when you click a button
  • During development, the HTML code is kept in a well-formatted separate header file. When uploaded to ESP, the HTML is stored in Flash memory using the Arduino Flash memory routines. When the program runs, the HTML is read in to RAM when needed. Many examples online that do this use the SPIFF file system instead of Arduino Flash memory routines. SPIFF requires separate manual uploads from the computer to the ESP. I didn’t want to learn that in this project, I already had too many things that could go wrong
  • CSS styles in the header – I knew I didn’t want to download online (Bootstrap or similar) CSS definitions to my ESP at runtime. Because then it will fail if there’s no Internet connection. One of the reasons to do this project to begin with, was to make it suffice with a local network

The circuits4you code is a bit hard to understand, partly because there are about 10 different variables and handlers with similar names, partly because of the involved parallel code structures in HTML, Javascript and C. That’s why people hate web development. Also there were some small errors in the code :) Anyone who has done some HTML can probably spot this one:

server.send(200,”text/plane”, ledState); //Send web page

It’s not like we’re going to send an airplane to the web server. Also, data stored in Flash memory can’t be read into a C String variable like this:

String s = MAIN_page; //Read HTML contents

I changed it to:

String s = FPSTR(MAIN_page);   //Read HTML contents

Here’s the finished ESP8266 code, which is actually an Arduino sketch. It could be optimized a bit, and the States and Steps could be better clarified but still

/*********
  9bit.se 2018
*********/

// #define MQTT_USE 0

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <Ticker.h>
#include "index_html.h"

MDNSResponder mdns;

// Network credentials
static const char* ssid = "XXXXXX";
static const char* password = "YYYYYY";

ESP8266WebServer server(80);
Ticker rtc_second_ticker;
Ticker blink_ticker;
Ticker step_1_ticker;
Ticker step_2_ticker;
Ticker step_3_ticker;

static const int gpio13Led = 13;
static const int gpio12Relay = 12;

int toast_sequence_short[3]  = {100, 30, 30}; // {toast, pause, toast}
int toast_sequence_medium[3] = {130, 30, 30};
int toast_sequence_long[3]   = {160, 30, 30};
int toast_sequence_extra[3]  = {0, 0, 30};
int *sequence;

int seconds; // Counting the progress of a toast sequence

String state_name;


// ---- Ticker callbacks: ----

void led_blink()
{
  digitalWrite(gpio13Led, !digitalRead(gpio13Led));  //LED blink
}


void add_second() {
    seconds++;
}


// ---- The toast program. Step durations stored in "toast_sequences" ----
// ---- Some of these functions are also ticker callbacks ----

void begin_toast() 
{
  seconds = 0;
  toast_step_1();
}


void toast_step_1()
{
  digitalWrite(gpio13Led, LOW);  //LED on
  digitalWrite(gpio12Relay, HIGH);
  step_1_ticker.attach(sequence[0], toast_step_2);
  rtc_second_ticker.attach(1, add_second);
}


void toast_step_2() // Pause
{
  digitalWrite(gpio13Led, HIGH);  //LED off
  digitalWrite(gpio12Relay, LOW);
  // blink timer here!!
  step_1_ticker.detach();
  step_2_ticker.attach(sequence[1], toast_step_3);
  blink_ticker.attach(0.5, led_blink);
}


void toast_step_3()
{
  digitalWrite(gpio13Led, LOW);  //LED on
  digitalWrite(gpio12Relay, HIGH);
  step_2_ticker.detach();
  blink_ticker.detach();
  step_3_ticker.attach(sequence[2], toast_step_4);
}


void toast_step_4()
{
  // End of program
  step_3_ticker.detach();
  rtc_second_ticker.detach();
  state_name = "Stop";
  digitalWrite(gpio13Led, HIGH);  //LED off
  digitalWrite(gpio12Relay, LOW);
}


void end_toast()
{
  state_name = "Stop";
  digitalWrite(gpio13Led, HIGH);  //LED off
  digitalWrite(gpio12Relay, LOW);
  step_1_ticker.detach();
  step_2_ticker.detach();
  step_3_ticker.detach();
  blink_ticker.detach();
  rtc_second_ticker.detach();
}


// ---- Handlers initiated by http requests ----

void handleRoot() // Serve Index.html, as defined in Flash memory
{
  String s = FPSTR(index_html); //Read HTML contents from Flash memory
  server.send(200, "text/html", s); //Send web page
}


void handle_progress() // Web page wants to know the width of the progress bar
{
  float percent = 0;
  float len = float(sequence[0] + sequence[1] + sequence[2]);
  
  if(len > 0) percent = 100 * float(seconds + 1) / len;
  if(percent > 100) percent = 100;
  if(state_name == "Stop") percent = 0;  // Reset the progres bar
  
  String progress = String(percent);
  
  server.send(200, "text/plain", progress);
}


void handle_action() // Web page button click selects toast sequence
{
  String s = server.arg("action");
  int server_action_state = s.toInt();

  if(state_name == "Stop") {
        
    switch (server_action_state) {
      case 1:
        {
          sequence = toast_sequence_short;
          begin_toast();
          state_name = "Short";
          break;
        }
      case 2:
        {
          sequence = toast_sequence_medium;
          begin_toast();
          state_name = "Medium";
          break;
        }
      case 3:
        {
          sequence = toast_sequence_long;
          begin_toast();
          state_name = "Long";
          break;
        }
      case 4:
        {
          sequence = toast_sequence_extra;
          begin_toast();
          state_name = "Extra";
          break;
        }
      case 0:
      default:
        {}
    }
  } else {
    if(server_action_state == 0) {
      // Stop
      state_name = "Stop";
      end_toast();
    }
  }
  
  server.send(200, "text/plain", state_name); //Send response to web server
}


// ---- setup, loop ----

void setup(void) {
  state_name = "Stop";
  sequence = toast_sequence_short;

  // preparing GPIOs
  pinMode(gpio12Relay, OUTPUT);
  digitalWrite(gpio12Relay, LOW); // Relay off

  pinMode(gpio13Led, OUTPUT);
  digitalWrite(gpio13Led, LOW);  //LED on

  WiFi.begin(ssid, password);
  Serial.begin(115200);
  delay(1000);

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  // Create a static ip adress
  IPAddress static_ip(192, 168, 10, 92);
  IPAddress gateway_ip(192, 168, 10, 1);
  IPAddress subnet_mask(255, 255, 255, 0);
  WiFi.config(static_ip, gateway_ip, subnet_mask);

  Serial.println();
  Serial.println();
  Serial.println("Connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (mdns.begin("esp8266", WiFi.localIP())) {
    Serial.println("MDNS responder started");
  }

  server.on("/", HTTP_GET, handleRoot);
  server.on("/select_action", handle_action);
  server.on("/progress_update", handle_progress);

  server.begin();
  Serial.println("HTTP server started");

  digitalWrite(gpio13Led, HIGH);  //LED off
}


void loop(void) {
  server.handleClient();
}

And here’s the code for the HTML page. It needs to sit in a file called index_html.h next to the main sketch file

static const char index_html[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<style>
*{
    box-sizing: border-box;
}
label {
    padding: 12px 12px 12px 0;
    display: inline-block;
}
button {
    background-color: #1080AF;
    color: white;
    width: 100%;
    padding: 32px 20px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    float: left;
    margin-top: 12px;
    margin-bottom: 12px;
}
button:hover {
    background-color: #00608F;
}
.container {
    border-radius: 5px;
    padding: 20px;
    width: 300px;
}
.row:after {
    content: '';
    display: table;
    clear: both;
}
.progress-container {
	background: #d0d0d0;
}
#progress-bar {
	background:red;
	height:20px;
	width:0;
}
@media screen and (max-width: 600px) {
    container {
        width: 100%;
        min-height: 50px;
    }
}
</style>
</head>

<body>
<div class='container'>
  <div class="progress-container"">
	<div id="progress-bar"></div>
  </div>
  <span id="display"> </span>
  <div class='row'>
    <button type="button" name="Short" onclick="sendData(1)">SHORT (120 + 30s)</button>
  </div>
  <div class='row'>
    <button type="button" name="Medium" onclick="sendData(2)">MEDIUM (160 + 30s)</button>
  <div class='row'>
    <button type="button" name="Long" onclick="sendData(3)">LONG (180 + 30s)</button>
  </div>
  <div class='row'>
    <button type="button" name="Extra" onclick="sendData(4)">EXTRA (30s)</button>
  </div>
  <div class='row'>
    <button type="button" name="Stop" onclick="sendData(0)">STOP</button>
  </div>
</div>
</body>

<script>
function sendData(data) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      // document.getElementById("display").innerHTML = this.responseText;
      if(this.responseText == "Stop") {
        var elem = document.getElementById("progress-bar");
        elem.style.width = '0%';
      }
    }
  };
  xhttp.open("GET", "select_action?action="+data, true);
  xhttp.send();
}

setInterval(function() {getData();}, 2000); //2000 mSeconds update rate

function getData() { // The progress bar
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
  	  var elem = document.getElementById("progress-bar");
      elem.style.width = this.responseText + '%'; 
    }
  };
  xhttp.open("GET", "progress_update", true);
  xhttp.send();
}
</script>
</html>
)=====";

Toasting

Upper Left is the Sonoff. The Green Led shows the state: On for Toast, Flashing green for Pause


Helpful links

Reprogram Sonoff Smart Switch with Web Server
https://randomnerdtutorials.com/reprogram-sonoff-smart-switch-with-web-server/

ESP8266 ajax – update part of web page without refreshing
https://circuits4you.com/2018/02/04/esp8266-ajax-update-part-of-web-page-without-refreshing/

ESP8266 Timer / ticker examples
https://circuits4you.com/2018/01/02/esp8266-timer-ticker-example/

Doepfer MCV4 Mod for Roland SH5


It seems Doepfer cut some corners when designing the MCV4 MIDI to CV interface. Firstly the MCV4’s gate voltage is to low to drive the Roland SH5 gate input. This can be remedied by opening up the interface to move a jumper, and then replacing the 9v power supply with a 12 volt one. After that the MCV4 controlled the SH5 gate and Pitch CV as expected. But it had no effect on the filter at all. That is because the output from the DAC isn’t buffered, and the DAC itself cannot drive the load of the Filter CV input. An MCP6002 OpAmp was connected as a basic voltage follower to buffer the Note Velocity output.

Beware that the image shows an unsuccessful experiment with a TL072, that has a different pin configuration.

Don’t use this image as a guide for connecting the MCP6002!

Kawai R-100 MIDI-Controlled Pitch and Circuit Bend Mod

A mid-80’s drum machine, modified for MIDI-controlled sound chip selection, circuit bending and pitch. Any MIDI sequencer or keyboard can be used. No changes are made to the exterior of the machine.

The Kawai R-100 drum machine classic was modified using an Arduino Nano, the circuitbenders.co.uk “R-ROM Switcher” and a HC-SR08 board. The Nano reads incoming note data on MIDI channel 2 to control the HC-SR08 and ROM Switcher board. Incoming MIDI data can

  • Control the playback pitch of the entire machine
  • Select sound ROM chip
  • Control a couple of the circuitbend connection points

The pitch mod: The HC-SR08 is a development board for the Analog Devices AD9850 Direct Digital Synthesis chip. The output DDS frequency is controlled by The Nano, reading MIDI notes and pitch bend. The output square wave is used as a clock signal for the R-100’s Address Generation Unit. This means that when the Kawai R-100 tries to play any sound, the rate at which the sound sample data bytes are found in memory is set by the 9850 output.

Actually this can be done without the HC-SR08, only using a pwm output on the Nano. This is how I originally tested the idea. But while this would work fine for very low pitches, the closer you’d get to the R-100’s original pitch, the less pitch resolution you would get. Since I wanted to be able to play it in a resolution of semi-tones (or even cents, using pitch bend) I had to use a higher resolution clock generator :)

The circuit bend: There are pre-made circuit bend points in the ROM Switcher pcb. It’s sufficient to have the Nano connecting these points to ground, they don’t need to be interconnected. To get back to non-circuit bent sound, the Nano pins are left in a floating state. The sound quality of the bends are much like a comb filter or phaser.

The ROM chip selection: To enable one ROM chip, the original ROM-Switcher connects the Output Enable (or possibly Chip Enable) pin of that chip to ground. Others are in HIGH state. A very simple task for a microcontroller.

Instruments for exhibition – Control Surface

Two unusual electronic instruments that were part of a greater ensemble, built for an exhibition in China. Idea and hardware by Daniel Araya. Programming and I/O-electronics by 9bit.

The MIDI Control Surface

The Control Surface is a Standard MIDI Interface compliant unit, built to interface with a MAX MSP patch on a host computer. The Control Surface has about 40 faders, knobs, switches, touch controls and a status LED that is controlled from within MAX MSP.

Testing the first of the eight really nice capacitive touch controls

This is testing MUXes and SPI port expansions on a CNC-made prototype PCB. MIDI on the Arduino Uno was only implemented as “MIDI over USB”, since it was not to be connected directly to other MIDI-capable instruments, only to a computer running host software.

Boxing it…

Instruments for exhibition – Metronomes

Two unusual electronic instruments that were part of a greater ensemble, built for an exhibition in China. Idea and hardware by Daniel Araya. Programming and I/O-electronics by 9bit.

The Metronomes

Three metronomes were built, one master and two slaves. The tempos of the slave units are synced to the master but the beat patterns that they play differ. The pattern generation algorithms used are mostly Euclidean Polyrhythms of varying lengths and “densities”. Thank’s to Wouter Hisschemöller’s page for cutting my firmware dev time.

The master unit features a tempo knob, sync-to-slave output, metronome beep, metronome light flash, DMX output.

The slave units feature a pattern length knob, pattern density knob, sync-to-master input, metronome beep, metronome light flash, DMX output.

Analyzing a DMX signal

DMX sync test

Wrapping it up

Avrdude – Burn fuses (16 MHz clock out on CLK0 / B0)

Reason

Fuses. There are a couple of user selectable operation modes of the AVR microcontrollers. The fuses can’t be edited in the same way you normally program you Arduino. You will need a hardware AVR programmer, ie the one described here: Arduino as ISP. There are a few GUI softwares that are supposed to do this, but I couldn’t get any of the Mac OS X ones to connect to my Arduino/Genuino Uno, so I used AvrDude from the Terminal.

I wanted to do this in order to get a 16 MHz clock output on the Arduino Digital pin 8 / B0 / CLK0. This signal was to be used as a Reference Clock for the AV9110 Serially Programmable Frequency Generator.

 

Parts list

• AVR Programmer
• Arduino Uno
• AvrDude software

 

Setting (aka Programming) the fuses

Step 1, find out the new fuse settings
Use this site to get the hex numbers for your new fuse settings: http://www.engbedded.com/fusecalc (If you don’t understand the contents of this site you need to read your AVR docs, search the web, or ask yourself if you really need to change any fuses.)

Step 2, burn the fuses with AvrDude

In your shell, type avrdude. (If it says unknown command or similar, you need to CD to the directory where AvrDude is on your Mac.) If it presents a list of AvrDude parameters you’re good to go. This command changes the CKOUT fuse so the system clock is output on B0:

avrdude -c stk500v1 -p m328p -P /dev/cu.wchusbserial410 -b 19200 -U lfuse:w:0xBF:m -U hfuse:w:0xD2:m -U efuse:w:0x04:m 
-c stk500v1 (programmer is Arduino as ISP)
-p m328p (Microcontroller name)
-P /dev/cu.wchusbserial410 (port name)

The above settings can be gathered from the output of the Arduino IDE when uploading a sketch to your Arduino. Please turn on “Verbose Output when uploading”.

lfuse:w:0xBF:m -U hfuse:w:0xD2:m -U efuse:w:0x04:m (New fuse settings)

These are the new fuse settings from http://www.engbedded.com/fusecalc. I was mainly interested in CKOUT = true. Setting the fuses wrongly can make your Arduino unresponsive. Please read up on which fuses NOT to change, prior to experimentation.

Analog Joystick

Connect an analog joystick to an Arduino. Read two analog values (x- and y-position) and a switch using a method witch does not hog the processor during the whole ADConversion.

The capacitor reduces digital noise on the analog readings.
Joystick

Code

static const byte ADC_CHANNEL_JOYSTICK_X = 0;
static const byte ADC_CHANNEL_JOYSTICK_Y = 1;

static const byte ADC_CHANNEL_MAX = 2;

byte adc_channel = 0;
bool joystick_button = 0; // 1 or 0
uint16_t joystick_x = 0; // 0~1023
uint16_t joystick_y = 0; // 0~1023


void setup() {
 Serial.begin(115200); // Remove
 
 pinMode(A0, INPUT); // Analog pin A0
 pinMode(A1, INPUT); // Analog pin A1
 pinMode(2, INPUT_PULLUP); // Digital pin 2
 
 // Setup adc
 ADCSRA |= 1 << ADEN; // Enable ADC, with no interrupt!
 ADCSRA |= ((1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0)); // Main clock / 128
 ADMUX = adc_channel; // Channel
 ADMUX |= 1 << REFS0; // Aref pin -> 100nF -> gnd
 ADCSRA |= 1 << ADSC; // Start first conversion
}


void loop() {
 byte changed = 0;
 
 // Analog
 if ((ADCSRA & (1 << ADSC)) == 0) { // ADC done
 changed += read_analog();
 }

 // Digital
 changed += read_digital();

 // Tmp
 if(changed > 0) {
 Serial.print("x: ");
 Serial.println(joystick_x);
 Serial.print("y: ");
 Serial.println(joystick_y);
 Serial.print("button: ");
 Serial.println(joystick_button);
 Serial.println();
 }
 delay(100); // Remove
}


byte read_digital() {
 byte state = 0;
 byte val = !(bool)(PIND & 0b00000100); // PORT IN D, pin nr 2
 if(val != joystick_button) {
 state = 1;
 joystick_button = val;
 }
 return state;
}


byte read_analog()
{
 byte state = 0;
 uint16_t val = ADC; // ADC is the full 10-bit, two-register, value from the last ADConversion
 
 switch(adc_channel) {
 case ADC_CHANNEL_JOYSTICK_X:
 if(joystick_x != val) {
 state = 1;
 joystick_x = val;
 }
 break;
 case ADC_CHANNEL_JOYSTICK_Y:
 if(joystick_y != val) {
 state = 1;
 joystick_y = val;
 }
 break;
 }

 adc_channel++;
 if(adc_channel >= ADC_CHANNEL_MAX) adc_channel = 0;
 ADMUX = adc_channel; // Channel
 ADMUX |= 1 << REFS0; // Aref pin -> 100nF -> gnd
 ADCSRA |= 1 << ADSC; // Start next conversion
 
 return state;
}


Avrdude – Upload hex file to Arduino using ISP / ICSP

Reason

In some cases USB cannot be used to program (upload hex file to) a processor on an Arduino board. One such case is when you are targeting the second processor on an Arduino Uno, the ATMega16u2 whose sole purpose is to cater for USB communication.

Please note: Only the original style Arduino Uno R3 boards have an ATMega16u2 processor, so be sure to use one of those for target.

Another case arises after we succeeded in reprogramming the USB chip. In my case it will become a MIDI communication chip, so USB connectivity is lost and the main processor (ATMega328p) will also have to be programmed with ISP (In-System Programming).

Parts list

• Arduino IDE (I used arduino.cc 1.6.7 but any fairly modern will do)
• 2x Arduino Uno R3 (one programmer and one target)
• Hacked ICSP flat cable
• 3x LED / 3x 1k resistors (optional)

More info on the ISP / ICSP cable and connections at Nick Gammon’s

Using an Arduino board as ISP

Step 1, create an ISP programmer
Locate the ArduinoISP example sketch in the Arduino IDE. Upload it to the Arduino board that is to become the programmer. (The programmer board doesn’t necessarily have to be an original Uno, it may use an FTDI232 or CH340 chip for USB communication.)

Step 2, connect the boards
To upload a hex file to the USB-chip (m16u2 aka ATMega 16u2) on an Arduino Uno, you need to connect the programmer’s ISP header to the target board’s second ISP header. (If there is only one 6-pin ISP-header, you don’t have the original UNO.)

Step 3, upload hex file

Shell command

Uploading a pre-compiled hex file to the m16u2 USB controller on an Arduino Uno R3 board, using avrdude and an “Arduino as ISP”-programmer to target the m16u2.

/path/to/avrdude -C /path/to/avrdude.conf -v -p m16u2 -c stk500v1 -P /path/to/serial/port -b 19200 -U flash:w:/path/to/hex/file.hex 

Example

What you see is:
Using Terminal on Mac OS X
Uploading Hiduino midi firmware
from the folder “jobb/EMS/”
Using the “avrdude” that comes bundled with Arduino IDE
Using /dev/cu.wchusbserial410 (the serial port of the “Arduino as ISP”-programmer)

/Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin/avrdude -C /Applications/Arduino.app/Contents/Java/hardware/tools/avr/etc/avrdude.conf -v -p m16u2 -c stk500v1 -P /dev/cu.wchusbserial410 -b 19200 -U flash:w:/Users/gaunitz/Documents/Jobb/EMS/hiduino-master/compiled_firmwares/arduino_midi.hex 

The hard part is to get the file paths right. To get some hints, go to the Arduino IDE preferences and turn on “Show verbose output during -> Upload”. Then upload any sketch to an Arduino, and examine the log output.

After uploading the firmware I connected the target board to the computer with a USB cable and had a look in System Report:

Hiduino_in_system_report

The ATMega16u2 became a generic midi device, communicating with the ATMega328p :)

Digital Etch-A-Sketch by Mattias Green

A simple but effective project to demonstrate physical control over a computer screen.

  1. Connect two potentiometers to Arduino analog inputs A0 and A1
  2. Use serial-communications to get pot values from Arduino to Processing
  3. Make a Processing sketch that accepts the serial data and draws lines

 Arduino Code

void setup() {
  // Start serial-communications with computer:
  Serial.begin(9600); 
}

void loop() {
  delay(1);
  int sensorValueA = analogRead(A0); // Read pot at pin A0
  delay(1); // Wait between AD-conversions
  int sensorValueB = analogRead(A1); // Read pot at pin A1
  
  // Send variable contents over serial:
  Serial.print(sensorValueA);
  Serial.print(",");
  Serial.println(sensorValueB);
  // The formatting above is important when using more 
  // than one variable
}

Please take a moment to think about how the variable values will be presented to Processing. You cannot just Serial.println(var1); Serial.println(var2); If you’d do that, there would be no way for processing to know which value comes from which variable. To help parsing the data in Processing, print the values on the same line, separated by a comma.

Now, processing will se your two values like this: 233,856 and they will be considered a text String, not numeric values. (233 would be the value at Arduino pin A0 and 856 at A1.) You can easily convert such a string of words delimited by commas into an array of words.  Use split(str,delimiter) in Processing. “233,856” will be converted to [“233”, “856”] and each item can be accessed individually, and treated as a numeric value.

Processing Code

Serial myPort; // Use the serial port:
 
float prevX = -1; // Store pot values here
float prevY = -1;

void setup() {
  size(1024, 800); // Set screen size
 
  println(Serial.list()); // Print all available serial ports. Figure out which one the arduino uses.
  myPort = new Serial(this, Serial.list()[5], 9600); // The [5] refers to the 6th serial port in the list
  myPort.bufferUntil('\n');

  strokeWeight(5);
  stroke(50); // Color
}

void draw() {
	// Nothing
}

void serialEvent(Serial myPort) {
  // This could probably be optimized a bit, 
  // but I don't have Processing at hand right now..
  String inString = myPort.readString();   // Read a string from the serial port
  String[] inValues = split(inString, ','); // Split comma separated string to array of strings
  float inX = float(inValues[0]); // Convert array item at index 0 to a float number 
  float inY = float(inValues[1]); // Convert array item at index 1 
  
  if((inX != prevX) || (inY != prevY)) { // Not necessary, this is to avoid drawing if pots haven't changed
    if((prevX > -1) && (prevY > -1)) {
      line(prevX, prevY, inX, inY); // Draw a line from the last recorded pot values to the current ones
    }
    prevX = inX; // Store the new pot values for next draw cycle
    prevY = inY;
  }
}

 

Proof of Concept ;)

(Does not work in Firefox for some WordPress-related reason)