SSHing to a Raspberry Pi behind a firewall (Eduroam)

The firewall at my university (Eduroam) prevents direct connections between two computer on the network on all ports. SSH-ing to an other computer is therefor not possible. However, when a connection is ESTABLISHED, this connection can be reused – for example the other way around! Let’s work on this.

Requirements: rpi, external server

Automate your ssh login from your rpi to your external server using (this link). Execute these commands using “sudo” because the startup script we’re going to edit is run as root.

edit /etc/rc.local and add:

ssh -fN -l [username] -R 2210:localhost:2222 [external server ip]

The 2222 is the ssh port on my rpi. Your rpi could use 22 (default) or any other port. The 2210 is the loopback port (per this link). Upon reset, this line should be processed without errors. Then, on the external server, connect back to the rpi using:
ssh -l pi -p 2210 localhost

and your ssh session is available!

Raspberry pi as high quality LFO generator

I’ve been experimenting with external LFO generators to modulate my MS20 mini. Working towards a small and portable solution, I first built a larger format prototype using my laptop, a Presonus Firestudio and a fresh copy of pyo (a Python module written in C to help digital signal processing script creation).

Nice results! But I want a smaller, dedicated device to generate a variety of LFO waveforms, with enough range in the frequency (say from 0.001Hz to 5k Hz) to make the LFO interesting.

Enter Raspberry Pi.

I already did some experiments with the Pi and pyo, a great combination even on the “classic Pi”. With the generation of simple waveforms, the load from the pyo process never exceeds the 10%. No problems there. Problems did arise in the audio out selection. Like the audio out on my MacBook Pro, the audio out of the HDMI chip on the Pi is obviously lowfiltered, thus not outputting waveforms with a frequency lower than ~1Hz. Too bad I can’t use my HDMI to VGA and audio cable for this LFO then.

S-PC-0203_7

Next option is a cheapo USB audio adapter, called “3d sound” and based on the C-Media CM108 audio chip.ux_a06091200ux0003_ux_c Some first experiments conform this adapter to be adequate for the LFO job! Nice looking waveforms, going down to at least 0.01Hz (100 seconds). Too bad it has a DC offset of +2V. On decent audio hardware this is 0V. I tried a solution by Mick @ Leeds49 to no avail, the DC offset did not change. A small opamp circuit is needed anyway to generate a bipolar voltage – that circuit will thus also remove the DC offset. A differential amplifier circuit should do the trick.

LittleBits synced to Volca Beats’ pulse clock

Recently I was fiddling with a set of LittleBits and I was trying to sync these (the LitteBits micro sequencer that is), to my Volca Beats. With the current lineup of LittleBits, this was impossible. Since the Volca Beats has a sync out (0V, 5V pulses with 15ms duration), the solution was not all too difficult. I just took a LittleBits wire, cut it in two, reconnected the VCC and the GND but connected the SIG to the signal connector of an 3.5mm jack plug; this is shown in the schematic below.

littlebits_volca_schem

While this was working, I really wanted to have more control over the sync rate, e.g. double, quadruple, or half the BPM from the Volca Beats (or any other clocksource). Solutions using only IC’s or other non-microcontroller components seemed to difficult or complex (if any were found at all, can’t exactly remember). Time to develop some Arduino code than! Using pin 2 as the “sense” pin to detect the incoming pulses, the following code will lock on to that clockpulses, multiply the pulses by 4 or 8 and output the resulting multiplied pulses on pin 13 (easy to debug since the onboard LED will flash in sync with the outputted pulses).

// SINNEB.NET
// trigger in clock multiplier
// Arduino software to read a clock on pin 2 and multiply this clock times 4 or times 8
// output on pin 13

unsigned long delta_trigger_micros;
unsigned long prev_trigger_micros;
unsigned long triggers[7] = {0,0,0,0,0,0,0};

void setup() {
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);

  // execute "rising" on RISING interrupt on pin 2
  // pin 2 is connected to the KORG VOLCA BEATS
  // which sends a 15ms, 5V pulse every half beat
  attachInterrupt(0, rising, RISING);
}

void loop() {
  // continuesly scan the trigger array, which is setup by the "rising()" function
  // all 4 of 8 triggers lie in the future
  // when the micros() clock passes a trigger, that trigger is fired (flipPin13)
  // and the trigger is set to 10seconds in the future, waiting to be updated by the "rising()" function
  for(int x = 0; x < 7; x++){
    if(triggers[x] < micros()) {
      flipPin13();
      triggers[x] = micros() + 10000000;
    }
  }
}

void flipPin13() {
  digitalWrite(13, digitalRead(13) ^ 1);
}

void rising() {
  digitalWrite(12, digitalRead(12) ^ 1);
  flipPin13();

  // sync the multiplied clock with the slow clock after a rapid tempo change
  if (digitalRead(12) == HIGH) {
    if (digitalRead(13) == LOW) {
      digitalWrite(13,HIGH);
    }
  }

  // calculate delta between consecutive triggers
  // this "delta_trigger_micros" is used to calculate and activate "in-between" triggers
  delta_trigger_micros = micros()-prev_trigger_micros;
  prev_trigger_micros = micros();

  // split the delta_trigger_micros in a number of subtriggers to
  // multiply the interrupt clock signal
  // every division, a trigger is placed in the trigger array
  for(int x = 0; x < 7; x++){
    triggers[x] = micros() + (((x+1.0)/8.0) * delta_trigger_micros);
  }

}

To divide the Arduino output into different clockspeeds, a CD4017 decade counter is deployed. The Arduino drives the clockpin, a button is connected to the clock enabled pin to “pause” the clock to influence the sync and the reset pin is connected to one of the divider outputs. Depending on the selection of the multiplication by the Arduino (4x or 8x) and the selected divider output, pin 3 of the CD4017 sends out the new clock.

Untitled

I uploaded 2 Youtube videos to demonstrate this!

The heated CA3046, part 1

A reliable VCO needs a steady exponential converter. Exponential converter are, because of their transistor based design (needed for the exponential functions), very temperature sensitive. A number of solutions to this problem exist. A solution that looks very interesting from a technical point of view is the solution found in (among others) the Moog Prodigy. The exponential converter only needs two transistors (the matched pair) from the five transistor available in the CA3046 chip. The Prodigy uses one of the left over transistor to heat the entire chip. An other transistor is deployed to measure temperature (the CA3046 transistors have a -2mV per centigrade temperature sensitivity). This measurement is compared by a comparator to stop or start the heating and keep the chip at a 55 degrees temperature.

First simulation: The temperature sensitivity of 1 of the transistors in the CA3046

tempchip

Result: The transistor shows a temperature sensitivity of around -2mV per centigrade (first 5 temp.steps shown):

tempresults

According to the simulation, the voltage at 20 degrees Celcius is 621mV and the voltage at 55 degrees Celcius is 553mV

LM13700 Triangle VCO

The LM13700 OTA chip has an interesting schematic for a triangle VCO in its datasheet. The discreet sawtooth VCO I’m building is too complex for breadboarding and does not deliver a decent sawtooth (probably due to distortion picked up somewhere in the breadboard). Therefor I decided to give the LM13700 triangle VCO a go. The schematic in the datasheet is very clear. All I did was exchange some resistor and capacitor values to ones that I have laying around. I also wanted to achieve a waveform at an audible frequency so I calculated values for a waveform around 500Hz.

LM13700trianglevco

The minus input on the second LM13700 has the triangle wave output. The Darlington output on the second LM13700 has the square wave output. The triangle looks like this:

trianglewaveoutput

and sounds like this:

Building an exponential converter

In this article I’ll describe the steps I took to design an exponential converter. YMMV of course, but I think this article is a good start and may provide some useful guidelines.

The following table shows the relation between Hertz and wavelength. These are the MIDI C notes per octave, in Hz with their corresponding wavelength in ms

8.1757989156 hz
122.312205856 ms

16.3515978313 hz
61.156102927 ms

32.7031956626
30.578051464

65.4063913251
15.289025732

130.8127826503
7.644512866

261.6255653006
3.822256433

523.2511306012
1.911128216

1046.5022612024
0.955564108

2093.0045224048
0.477782054

The required wavelength a capable VCO should be able to deliver thus lays between 122ms and 0.47ms. Experimenting with a slightly customised sawtooth generator (design below) shows the following relation between the (ideal) current source and the wavelength.

0.1ua -> 470ms
1ua -> 47ms
10ua -> 4.7ms
100ua -> 0.47ms (470us)
1000ua (1ma)-> 0.047ms

First, the slightly customised sawtooth VCO. The inverting Schmitt trigger in the sawtooth reset circuit guarantees a long enough reset pulse and thus a clean reset of the sawtooth waveform. The capacitor is too large, leading to a small distortion in the waveform. Will be fixed in updates.

sawtoothVCO600
sawtoothvco in PDF

The current source (exponential converter) must deliver a steady current between 0.1ua and 1000ua to the VCO to have to VCO achieve interesting musical abilities (enough octaves, very low frequencies, MIDI controllable). The deployment of an exponential converter in this current source is almost inevitable. Linear control, preferable digital through DAC’s or such, of a current source with such a bandwidth (0.1ua -> 1000ua) is very difficult.

The circuit of the exponential converter:

expcurrentsource

The formula for the exponential part of the converter is iout = iref * exp(-Vb/Vt) where vt = 26mV.

iref runs over R1 => iref = Vref / Rref = 15V / 1000000ohm = 0.000015A = 15uA. To achieve an output current of 0.1ua (the VCO will generate a 470ms waveform) => 0.1 = 15 * exp(-Vb/26) => Vb = 130mV. Some calculations of Vb in the required bandwidth of 0.1ua and 1000ua:

wavelength: current -> required voltage
470: 0.1ua -> 130mV
235: 0.2ua -> 111mV
118: 0.4ua -> 94mV
59: 0.8ua -> 76mV
30: 1.6ua -> 58mV 
15: 3.2ua -> 40mV
8: 5.9ua -> 24mV
4: 11.75ua -> 6mV
2: 24ua -> -12mV
1: 47ua -> -30mV
0.5: 94ua -> -48mV
0.25: 188ua -> -66mV

This leads to a relation between linear voltage and exponential current! Required to translate a difference of 1 volt to a musical difference of 1 octave (which is a exponential scale).

The voltage into the exponential converter will thus have a 1V/octave scaling and start at 0 volts (130mV) up to 12 volts (-66mV). The base voltage will be 130mV. The voltage scaling opamp will have to scale the incoming voltage (0-12V) to a -18mV per Volt. This voltage is buffered by an opamp follower and a voltage summer then combines the base voltage and the voltage scaler voltage (note to self: make the 1k in the summer smaller for a more precise summer).

voltagescaler

The exponential converter takes this voltage (in V4) and transforms it into a current source following calculations above. Temperature drifting and transistor matching have not been explored in full. For now the CA3046 is deployed. Temperature compensation is probably achievable by driving the other transistors in the CA3046 to a certain temp (like in the Moog Prodigy).

SPI control of AD9833

A few months ago I ordered a MSOP to DIP conversion board including an AD9833 from proto advantage.  The AD9833 (LOW POWER, 12.65 MW, 2.3 V TO +5.5 V, PROGRAMMABLE WAVEFORM GENERATOR) looks like an interesting IC, doesn’t cost too much and is perhaps suited for a musical purpose.

Wiring up and controlling the AD9833 took some time and some research but I finally combined the right pieces of the puzzle.

124

At first I wired up the power section as proposed in the datasheet:

Screen Shot 2013-04-15 at 12.35.32 PM

Lots of attention to decoupling and separation of DGND and AGND, which both are a good thing ™ but also clutter my experimental setting on the breadboard. So, time to reduce the number of components with the setup from NXR:

AD9833Connsmall

Much better.

Annem did a great job interfacing the AD9837 with the Arduino. Fortunately, the AD9833 has the same interface. I did however make some adjustments. I removed the delay in re-activating the AD9833. I added the Timer1 library to generate the masterclock for the AD9833. This clock runs in the background at ~1Mhz and is made available through pin 9.


/*
AD9837 Pro Generator sample code
This was written in Arduino 1.0.1,
for an Arduino Pro Mini, 5V, 16MHz
Pete Dokter, 9/2/12
Remixed by Anne Mahaffey, 10/8/12
ReRemixed by sinneb, 15th of april 2013

The connections to the AD9837 board are:

FSYNC -> 2
SCLK -> 13 (SCK)
SDATA -> 11 (MOSI)
MCLK -> 9 (Timer1)
+Vin = VCC on Pro Micro
GND -> GND

This code bears the license of the beer. If you make money off of this,
you gotta beer me.
*/

long freq; //32-bit global frequency variable

#include <SPI.h>
#include "TimerOne.h"

// Define the FSYNC (used for SD funtion)
#define FSYNC 2

&nbsp;

void setup()
{
 Timer1.initialize(1);
 Timer1.pwm(9, 512);

 pinMode(FSYNC, OUTPUT); //FSYNC

 Serial.begin(9600); // start serial communication at 9600bps

 digitalWrite(FSYNC, HIGH);

 SPI.setDataMode(SPI_MODE2); // requires SPI Mode for AD9837
 SPI.begin();

 delay(100); //A little set up time, just to make sure everything's stable

 //Initial frequency
 freq = 4000;
 WriteFrequencyAD9837(freq);

 Serial.print("Frequency is ");
 Serial.print(freq);
 Serial.println("");

}

void loop()
{

}
void WriteFrequencyAD9837(long frequency)
{
 //
 int MSB;
 int LSB;
 int phase = 0;

 //We can't just send the actual frequency, we have to calculate the "frequency word".
 //This amounts to ((desired frequency)/(reference frequency)) x 0x10000000.
 //calculated_freq_word will hold the calculated result.
 long calculated_freq_word;
 float AD9837Val = 0.00000000;

 AD9837Val = (((float)(frequency))/16000000);
 calculated_freq_word = AD9837Val*0x10000000;

 /*
 Serial.println("");
 Serial.print("Frequency word is ");
 Serial.print(calculated_freq_word);
 Serial.println("");
 */

 //Once we've got that, we split it up into separate bytes.
 MSB = (int)((calculated_freq_word & 0xFFFC000)>>14); //14 bits
 LSB = (int)(calculated_freq_word & 0x3FFF);

 //Set control bits DB15 ande DB14 to 0 and one, respectively, for frequency register 0
 LSB |= 0x4000;
 MSB |= 0x4000;

 phase &= 0xC000;

 WriteRegisterAD9837(0x2100);

 //delay(500);

 //Set the frequency==========================
 WriteRegisterAD9837(LSB); //lower 14 bits

WriteRegisterAD9837(MSB); //upper 14 bits

WriteRegisterAD9837(phase); //mid-low

 //Power it back up
 //AD9837Write(0x2020); //square
 WriteRegisterAD9837(0x2000); //sin
 //AD9837Write(0x2002); //triangle

}

//This is the guy that does the actual talking to the AD9837
void WriteRegisterAD9837(int dat)
{
 digitalWrite(FSYNC, LOW); //Set FSYNC low
 delay(10);

 SPI.transfer(highByte(dat)); Serial.println(highByte(dat));
 SPI.transfer(lowByte(dat)); Serial.println(lowByte(dat));

delay(10);
 digitalWrite(FSYNC, HIGH); //Set FSYNC high
}

I added a buffering opamp to listen to the generated sinewave. Sounds pretty OK to me. Now off to further investigate the audio possibilities of this IC.

Calculating Landolt C ring size based on the visual acuity

Landolt Ring

Tiny Python script to calculate the size (5d) in meters of a Landolt C ring based on the visual acuity belonging to that ring.


# determine Landolt C ring size based on decimal visual acuity scales
# argument: visual acuity [0.1 ... 3]
# result: size of Landolt C ring (5d in the image) (in meters)
# http://upload.wikimedia.org/wikipedia/de/2/27/Landoltring.jpg

import math, sys

# distance from ring in meters
distance = 5

print 2*distance*math.tan(math.radians(1/(float(sys.argv[1])*120)))*5

landolt C Chart

Row 8 in the picture to the left shows Landolt rings to determine a decimal visual equity of 1. Use 1 as argument in the Python script and it will return 0.00727220526792, which means the size of that ring when viewed from 5 meters is 7.27 millimeters.

Kivy and vite-vite

Note to self: Use Kivy (Open source Python library for rapid development of applications for multiple platforms) and vite-vite (Toolkit for building business and productivity apps on Android using the Kivy framework) for next prototype.

Livestream webcam via webm to browsers

Here’s a work in progress: livestream webcam video to browsers using Node.js. From here. Ubuntu requires the ‘nodejs’ executable instead of just ‘node’

var express = require('express')
var net = require('net');
var child = require('child_process');

var cmd = 'gst-launch-0.10';
var args = '';
var options = null;

var app = express();

app.get('/', function(req, res) {
  var date = new Date();

  res.writeHead(200, {
    'Date':date.toUTCString(),
    'Connection':'close',
    'Cache-Control':'private',
    'Content-Type':'video/webm',
    'Server':'CustomStreamer/0.0.1',
    });

  var server = net.createServer(function (socket) {
    socket.on('data', function (data) {
      res.write(data);
    });
    socket.on('close', function(had_error) {
      res.end();
    });
  });

  server.maxConnections = 1;

  server.listen(function() {
    args =
    ['v4l2src device=/dev/video0',
    '!', 'video/x-raw-rgb,framerate=30/1',
    '!', 'ffmpegcolorspace',
    '!', 'vp8enc', 'speed=2',
    '!', 'queue2',
    '!', 'm.', 'audiotestsrc', 'is-live=1',
    '!', 'audioconvert',
    '!', 'vorbisenc',
    '!', 'queue2',
    '!', 'm.', 'webmmux', 'name=m', 'streamable=true',
    '!', 'tcpclientsink', 'host=localhost',
    'port='+server.address().port];

    var gstMuxer = child.spawn(cmd, args, options);

    gstMuxer.stderr.on('data', onSpawnError);
    gstMuxer.on('exit', onSpawnExit);

    res.connection.on('close', function() {
      gstMuxer.kill();
    });
  });
});

app.listen(9001);

function onSpawnError(data) {
  console.log(data.toString());
}

function onSpawnExit(code) {
  if (code != null) {
    console.error('GStreamer error, exit code ' + code);
  }
}

process.on('uncaughtException', function(err) {
  console.debug(err);
});