Controlling TXo, ER-301, etc wirelessly using OSC, Node and a RPI

The idea is to have a Raspberry Pi Zero W hidden in the Eurorack case, and powered by the case. It receives OSC sent from various devices and transmits the messages to an I2c follower on the i2c bus. It’s been tested successfully with TXo and I’m trying to make it work with an ER-301 too and I would need some help for that.
There are several other options to achieve the same result, including Norns + Crow of course but in this specific case I wanted something not requiring additional cables and devices.


Objective:

To put it briefly, my initial goal was to control the ER-301 from an iPad, by sending OSC mesages from TouchOSC or Lemur. At the moment, the ER-301 is not supported (see below) but the setup works fine with a TXo and could probably work with other follower modules on the I²C bus. It uses OSC, sends I2C and the “conversion job” is handled by Node.js on a Raspberry Pi. The latency is very low.

Approach:

I explained my approach and detailed the steps on the O|D forum if you want to read the whole thing.

Unfortunately, I never managed to connect the RPI to the ER-301. That’s a big disappointment (explanations at the end of this post)

But considering that I have used a Txo for testing the process without risking to harm the ER-301, I will share the project anyway, even if it doesn’t supports the ER-301. I hope I can fix that with the help of this community.

Hardware:

I have considered several hardware solutions but I chose a RPI Zero W because it’s cheap (around 15€), it provides Bluetooth, Wifi and an additional micro USB port. The most important, I can power it from the 5V rail of a Eurorack case (it only draws around 220mA). The hardware I2c GPIOS are exposed, there are two (1.8k) pull-up resistors and a level of 3.3V. On the paper, it doesn’t need an additional circuit (Logic level shifter etc) to work and control an I2C capable module. For now I can only confirm that it’s working with Teensy based modules like TXo.

Software:

I wanted to prototype this idea as fast as possible. I don’t know Python or C++, I know Lua and JS.
So I decided to use Node.js, it’s fast, reliable and most importantly there are thousands of modules available.

After a bit of research, I found Node-red which is a node.js based open source « programming tool for wiring together hardware devices, APIs and online services. » Super reliable, it doesn’t need to write a lot of code, is accessible from a web browser and also has dozens of modules aka « nodes » available, ready to patch.

Preparing the RPI for I2c takes a few minutes, and the node-red install is entirely scripted. 5 minutes to install, you open a web browser and start patching like you’d do in Max, TouchDesigner, Cables.gl etc. In case of problem, the documentation is excellent. The resulting patch is called a « flow ». Once ready, you « deploy » it to the Pi from a simple click.

So I got Max/MSP and Lemur talking to the PI via OSC in no time.

Following that, using the node-red patching environment I wrote some additional JS functions in order to process the OSC messages, pack them to nice JSON messages.
Then I send this to an « i2c node » which converts and sends the command to the i2c bus.
I’m not re-inventing the wheel, I’m using the Monome ii protocol and all the commands available.

The latency is ultra reasonable so far, I’m not fully done with the tests yet. I will do more « stress » tests once the entire set of commands is implemented.


the node-red patching environment

Roadmap:

I will publish the full node-red « flow » and install process on Github in a few days. I just need to add all the Txo commands before I publish it.

Technically, it could work with other i2c followers on the bus. It’s just a matter of adding the corresponding commands.

I wanted to use OSC, but Node-red has many other interesting nodes and it would be easy to add support for other inputs such as:

  • Leapmotion
  • Midi
  • any API
  • Midi over Bluetooth (Roli devices for example), this one is on my roadmap.

Downsides:

The Raspberry Pi is a Leader on the bus and unless you want to write some additional code for supporting multiple masters on the i2C bus (I can’t and won’t do that), it probably needs to be the only leader on the bus.


The problem with the ER-301

ER-301 -> Like I said, I can’t connect the Pi to the ER-301, this is so disappointing because it was the original plan. I’m not going to write here all the tests I did, trying to make it work, perhaps it’s better to leave that on the Orthogonal Devices forum but if somebody can help me to fix that, I would really really appreciate.

My knowledge in electrical engineering, software etc is very limited. A week ago, I didn’t know anything about the I2c bus and protocol but since then I’ve read a lot of material but still can’t fix the issue.

I’ve read that the RPI 3 and Zero hardware I2c doesn’t handle « clock stretching », there are a few workaround like lowering down the baud rate excessively or using another set of GPIO and creating a new software i2c bus. I tried this on a breadboard because in that case, the lines need some external pull-resistors but that didn’t help.

There are two scenarios:

1 - If I start the Pi before the 301, the ER-301 will simply not boot. I tried to monitor it’s UART output using an FTDI to USB cable, but nothing.

2 - If I start the 301 first or if both devices start together then impossible to find the 301 on the bus and the bus scan is really slow. It looks like a follower on the bus holds the line down and stuck the bus. Or could it be the Olimex pulling power from the Pi as it was suggested on the OD forum ?

I tried to give them a common GND by powering the Pi from the same case. Also tried to « regulate » the level and provide another set of pull-up resistors using a TT backpack (without TT connected) I tried many things but I’m running out of ideas and I don’t have a Logic analyzer or oscilloscope to test with.

10 Likes

I don’t have specifics to add here (just yet)… but for startup - you generally want your follower devices already powered on before the leader. Thus when the leader starts, it can scan and see available followers.

Sounds odd that an address scan would be very slow. What is the olimex device doing here? (debug?) Which device? I didn’t see that mentioned in your hardware setup above.

1 Like

The Er-301 runs on an Olimex AM3352-SOM board. Normally, I would power on both devices at the same time but during the tests I tried various scenarios. The bus scan returns nothing in both scenarios. When the 301 is connected, i2cdetect starts super fast and as soon as it encounters the 30* addresses it becomes ultra slow.

On the opposite, doing a bus scan when the only device on the bus is a TXO is super fast and returns an almost immediate result.

1 Like

What a cool project.

Dumb question: is your ER-301 a newer unit? I ask because older ER-301 units need to be modded before they can successfully communicate over i2c (this is for ER-301 board revision 7 - units manufactured before June 2018):

http://wiki.orthogonaldevices.com/index.php/ER-301/Teletype_Connection_Rev7

Other than that, in all of my experiments with the Teletype in coding up the operators I saw that it behaved flawlessly. The only thing that tripped me up (once) was that the base address for the ER-301 changed in v0.4 of the firmware to 0x3).

i2c on the ER-301 opens up a massive number of triggers and CV. It will be a beast once you successfully connect to it. :slight_smile:

2 Likes

Thanks ! :blush:

Yes, the 301 has a rev10 board and I’m used to control it from Teletype and Crow. I also have three TXo, one of them is connected to TT and the others are now on the Crow bus. Well I took one apart for this test and connected it to the RPI and it behaves really well, is immediately detected following an i2cdetect, I can trigger for example a tr.p from Max without noticeable latency.

This problem with the 301 is a mystery to me. I don’t know if the 301 still uses the same “Combo” UARt I2c port or if it uses one of the three dedicated I2c busses of the Olimex board. Perhaps, there’s a communication problem between the Pi and the 301 when this last one does it’s startup routine.

I wanted to know if the “clock stretching” the RPI was the problem so I set a second I2c bus on another set of GPio (software I2c) But this didn’t fix the problem. There’s a communication problem between the two and I don’t know if it happens because something affects the level of the lines and would require an additional circuitry or if the follower responds in a weird manner to the leader and breaks the bus. Sorry for my “newbie“ terms and explanation. I know you participated in the implementation of the I2c protocol for the 301 with Scanner Darkly and probably Tehn, and I’m grateful for that. I read all the related threads but couldn’t find an answer. Apparently the 301 used to freeze if it received an I2c message during its startup routine, I have no idea if this has been fixed or not. As far as I know, the RPi doesn’t send anything if it’s not asked to. The only thing I know is that the 301 doesn’t ACK in response to a bus scan.

does this help?

Notes for the Raspberry Pi 3B, 3B+ and Zero W
The I²C controller on the Raspberry Pi 3B, 3B+ and Zero W has its clock linked to the VPU core so as the VPU frequency changes depending on processor load so does the clock rate of the I²C bus. This can cause problems with any devices that expect a constant clock rate during communication.

To solve this issue the VPU core frequency must be set to a fixed frequency by editing /boot/config.txt. Open the file with nano using the command:

sudo nano /boot/config.txt

Add the following text to the bottom of the file.

core_freq=250

Save your changes, exit the nano editor and reboot

lifted from here

See also https://www.raspberrypi-spy.co.uk/2018/02/change-raspberry-pi-i2c-bus-speed/ - it mentions a dtparam for i2c_arm_baudrate

Do you know what baudrate the 301 is using?

1 Like

Thanks @okyeron
Yes, I already tried to set the core_freq in config.txt but only with the I2c1 bus, not the software one.
I also tried various baud rates, the default 100k, 50k, and even 10k. It seems to be a common way (as explained here) to deal with the “clock stretching” bug of the RPI.
I don’t know at which bus speed the 301 can operate but right now, it supports the standard 100k, also used by the Teletype.

I should set up a “software i2c” bus again on the RPI, and try more pull-up resistor values maybe… Last time I tried it didn’t work, I mean it worked fine with Txo but not with the 301, but at least that would remove the clock stretching issue from the troubleshooting list.

I just did an interesting test: I’ve completely disabled the i2c1 bus of the Pi but left the pi connected to the 301 (GND, SCL, SDA) and powered externally with the official power supply. It’s still preventing the 301 from booting normally…

I should mention that I’ve tried with the Pi directly connected to the 301 but also with the Pi connected to a Nordhat (without Norns installed on it, the I2c bus is not used by the DAC).
The board uses the same circuit as the 16n for its i2c output, 1N4148 diodes and pull-up resistors on both lines.

Perhaps the i2c lines need to be isolated ?
https://www.mikroe.com/i2c-isolator-click or


Edit:
I created a new “software i2c” bus using GPIO 23 and 24 (and GND), I want to avoid the internal pull-ups (1.8k) and I want to remove the “clock stretching” issue from the list.

Outside the RPI, I created a small circuit (using a Nordhat PCB) with just two pull-up resistors and four 1N4148. This time I put the exact value recommended for the i2c bus of the AM3352, ie 4.7k.
It still does not work and i2cdetect -y 3 struggles to do its bus scan, it’s super slow, almost twenty seconds ( ! ) Well, I don’t know what to try next on the hardware side, I could try this small circuit with the ISO1540 would help.


i’d recommend booting both devices with the i2c cable disconnected. Once both devices are fully booted, attachthe cable and see if things work.

From debugging some Crow&JF i2c issues while ER301 is on the bus, it turns out the ER301 boots the i2c pins in UART mode, then switches after ~7seconds to i2c. This means there is a moment where ER301 puts the bus into an unknown state.

The idea of connecting the cable to a live system avoids the startup quirks as the source of the problem.

In terms of the connection causing the ER301 not to boot, this likely means the RPi pins need to be set to ‘input’ (ie high impedance), no pullup/down mode. Electrically this is equivalent (enough) to being disconnected.

1 Like

Thanks @Galapagoose !

Ah, that’s exactly what I was trying to find out, I didn’t know if the 301 was still using the UART port. I suspected a misunderstanding between the RPI and the 301 because of this but having no material to verify it… Now it’s clear.

Isn’t it risky to “hot plug” the i2c bus ? Anyway, I will try that.

I thought it was set automatically by activating the hardware I2c bus on GPIO 2 and 3. I didn’t have issues with the Txo. But I will investigate.

FWIW - I believe this is not a huge concern if you’re using jumper wires (or a “keyed” plug) where there’s not much chance of shorting between lines. but… be careful anyways :slight_smile:

The hot plug warnings on 16n or others with a 1/8" minijack are due to possible shorts between lines as you plug or unplug the jack.

1 Like

Yeah, I just tried that, carefully… Nothing bad happened :slight_smile: but the bus scan still returns an empty grid.

I need to investigate the electrical issue now… I don’t know if I can set the i2c pins to “input”, aren’t they supposed to work in both directions ? As for the Pull up resistors on these ones, I think there’s nothing I can do to deactivate them.

Not 100% sure this applies to the i2c pins, but… here’s some python examples here for setting GPIO pin mode, etc:
https://learn.sparkfun.com/tutorials/raspberry-gpio

also:
https://www.raspberrypi.org/documentation/configuration/config-txt/gpio.md

1 Like

Thanks for the links, nope it doesn’t seem to apply to the i2c GPIO.

I just tried another thing. I’ve checked the voltage on both lines, with the 301 connected but powered off, then with the 301 connected and powered on.

I’m measuring 3.295V when it is off, but only 3.16V when the 301 is powered on. One of the two seems to draw current from the other (as cleverly assumed in this post) … and the line never fully rises back to 3.3V :disappointed: Consequence > the messages are not ACKed, bus is corrupted?
Do you think the I2c isolator mentioned earlier in this thread could fix/stabilize this ? Or is it happening because of an incorrect pull up resistor value ? This can probably be fixed with a small circuit, right ? I will run the same experiment with TXo tomorrow, the Teensy is more likely to draw less current but perhaps it’s happening in this config too. I also have a Terminal Tedium I can hack to expose its Gpio 2 and 3 in order to see if powering both the 301 and the Pi from the 12v rail solves the issue. I don’t know much about ee unfortunately…
if it’s impossible to connect the Pi to the 301 without a custom circuit, I’ll just try to install Norns on a Pi Zero and connect it to Crow… with cables :-)))

For a weekend project I may try implementing something similar to all (OSC over wifi) this using an ESP8266 microcontroller or a Teensy+ESP32 breakout.

I don’t have a ER301 to test with, but can try to get something working to my Meadowphysics as a demo.

2 Likes

I’m afraid to say it’s time for the logic analyzer, or at least a scope.

If it didnt work after hot plugging then there’s likely something up.

3.1V doesnt necessarily seem like a problem to me. Test with txO to see if it is lower in voltage too, then you’ll know if it’s RPi or ER causing the droop.

1 Like

Thank you both for your replies.

I would like to own a nice Rigol oscilloscope but it’s more than I can pay right now and a Logic analyzer is even more. The cheap analyzers found on Amazon might be a bit weak compared to Saleae devices, but maybe they’d work too for a “normal speed” bus ? There’s also this software Oscilloscope which works with Pigpio that I’m planning to try later.

I’m testing a few other things before giving up with the RPI.

It turns out that the drool was caused by a mistake of mine, a bad connection on the breadboard … :face_with_hand_over_mouth:

New tests today revealed that the voltage is very close to 3.3v in both scenarios (module on or off). One more time, I let the 301 boot and hot plugged the two lines and ground. No drool with the Txo either.

At this step, the voltage is still 3.3v. But right after the bus scan, the line is held low by the follower, and stays at 0v…

The I2c specs mentions that when this happens, the solution for recovering the bus is to send 9 clock pulses…

If the data line (SDA) is stuck LOW, the master should send nine clock pulses . The device that held the bus LOW should release it sometime within those nine clocks

At the moment, I’m trying to figure out how to send 9 clock pulses from the terminal :smile:. Such a bus_recovery method or “bus clear” doesn’t seem to be implemented within i2ctools (or maybe it is but there’s no documentation, so it’s hard to know) This feature is not implemented in the BCM2835 driver

I’m experimenting one more day with the Pi and if it doesn’t work I’ll probably switch to another method.

@okyeron The ESP8266 is an option I have considered. Teensy + ESP32 is also a great idea :slight_smile: There won’t be Node.js and node-red in this scenario but there are a lot of libraries available for Arduino and the code for talking to the ER-301 is already written, so… Yep, I’ll definitely get one if the RPi experiments fail again today.

What is the “bus scan” and how does it work (is there source we can look at?).

Perhaps you could try sending a ‘real’ command to ER301 and check for response. AFAIK there is no specified i2c protocol for scanning the bus (a lot of us have spoken about how to do it). I’ve also not seen that 9-pulses thing anywhere, though admittedly I’ve never read the i2c spec.

2 Likes

Yes, sorry I said bus scan but the command is i2cdetect It’s part of i2ctools It is documented here https://linux.die.net/man/8/i2cdetect

The nine clocks thing is documented here section 1.3

Yes I can try to do that, I’m going to search how. python probably.


Result :

Python equivalent of i2cdetect
#!/usr/bin/env python

import smbus

bus = smbus.SMBus(1) # 1 indicates /dev/i2c-1

for device in range(128):

      try:
         bus.read_byte(device)
         print(hex(device))
      except: # exception if read_byte fails
         pass

It returns nothing and pulls both lines down.

Oh… Now it’s working. :champagne:


  1. Apparently, the ER-301 needs 4.7k pull-up resistors and nothing else. This solves the “boot issues”.

  2. It absolutely hates the i2cdetect command.
    Thanks to your suggestion @Galapagoose I sent a simple tr.pulse to the ER-301 bus.write_byte_data(0x31, 0x05, 0x01) and it’s working.
    Every i2c on RPI tutorials encourage you to do this bus scan with a force command. When you remove the -f from i2cdetect -f 3 the console shows the following advice :expressionless: > WARNING! This program can confuse your I2C bus, cause data loss and worse!


Now that the i2c works with both TXo AND ER-301 I can continue to work on the node-red code :slight_smile: The only downside is that the setup will need an external circuit. Given the fact that the ER-301 apparently requires the usage of specific pull-up resistors, I cannot use the default i2c pins. I used a Teletype backpack for this experiment but I will design something.

5 Likes

If the issue is the resistors are too small (ie too much pullup current), it probably just means the signal is taking too long to hit the Low state. The other solution is to use a slower clock speed as it gives the clock pulses longer to settle to the low state (and be registered correctly by ER301).

2 Likes