‹ redAlertLightp5 Tweets ›

redThermoKontroll2

2013-09-30 16:25 electronics

For my upcoming solo at the Sound of Stockholm festival, I decided to rebuild my main wireless controller. Previously it used a Nordic nRF24L01+ transceiver as radio module, but the range wasn't great and communication often broke down during live performances. I don't know much about these things, but I guess that when the audience bring in mobile phones the radio spectrum quickly fills up.

So I constructed a new circuit from scratch and while I was at it also reworked the resistor ladders and other cablings inside the box. Now it's using WiFi. The new radio module I installed in the controller box is Adafruit's CC3000 WiFi Breakout, and as receiver, I use a small tl-wr703n WiFi router running OpenWRT.

The wireless range is now excellent and everything is a lot more stable. I could also drastically reduce the amount of data being sent by fixing the resistor ladders.

Circuit... (basically just one ATmega382p, a 16 channel ADC, voltage divider resistors and the WiFi module)

redThermoKontroll2 photo 0

Inside...

redThermoKontroll2 photo 1

Outside...

redThermoKontroll2 photo 2

100 Ohm resistor ladder...

redThermoKontroll2 photo 3

Below are parts list, schematics, firmware and a SuperCollider class.

redThermoKontroll (WiFi version) parts list:

1   4067 multiplexer
1   ATmega328p
1   16 MHz crystal
2   27p ceramic caps
1   socket 2x14 (28pin)
1   Adafruit CC3000 module
1   1x9 pin header
1   1x10 pin header
1   1x8 pin header
1   1x5 pin header

1   resettable fuse 1A
1   Zener diode 5.6V
1   0.1uF cap
1   100uF electrolytic cap
1   470uF electrolytic cap

10  220, 270, 330, 680, 1K, 2, 10K resistors
1   220 resistor for led

1   power jack
1   LDR
1   red led
redThermoKontroll schematics 2
//redThermoKontroll2
//redFrik 2013 GNU GPL v2
//updated 150920 - automatically send to IP x.x.x.99 (constructed from given DHCP IP)

//make sure to use Paul Stoffregen's branch of the Adafruit_CC3000 library
//and cc3000 firmware 1.24 (1.11.1)
//select board UNO and upload to a ATMEGA328P chip (using a usbtinyisp programmer)
//test in terminal with command: nc -ul 58100

#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>

#define WLAN_SSID       "xxx"
#define WLAN_PASS       "yyy"
#define WLAN_SECURITY   WLAN_SEC_WPA2

#define PORT            58100
#define DELAY           10
#define PINGRATE        2000

#define ADAFRUIT_CC3000_IRQ   3   //mega328 pin 5
#define ADAFRUIT_CC3000_VBEN  8   //mega328 pin 14
#define ADAFRUIT_CC3000_CS    10  //mega328 pin 16
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBEN, SPI_CLOCK_DIVIDER);
Adafruit_CC3000_Client client;

uint8_t buf[16];
byte last[] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

byte cnt = 0;
unsigned long time;

void setup(void) {
  Serial.begin(115200);  //debug

  //--pins
  pinMode(7, OUTPUT);         //led
  pinMode(6, OUTPUT);         //4067 d (DDD6)
  pinMode(5, OUTPUT);         //4067 c (DDD5)
  pinMode(4, OUTPUT);         //4067 b (DDD4)
  pinMode(2, OUTPUT);         //4067 a (DDD2)
  pinMode(A5, INPUT);         //4067 x
  pinMode(A4, INPUT_PULLUP);  //capa1 (right)
  pinMode(A3, INPUT_PULLUP);  //capa0 (left)
  pinMode(A2, INPUT_PULLUP);  //swiUp (up)
  pinMode(A1, INPUT_PULLUP);  //swiUp (down)
  pinMode(A0, INPUT_PULLUP);  //swiOn

  //--wifi
  flash(1);
  Serial.println(F("Starting"));
  if (!cc3000.begin()) {
    Serial.println(F("Unable to initialise the CC3000! Check your wiring?"));
    while (1);
  }
  flash(2);
  Serial.println(F("\nDeleting old connection profiles"));
  if (!cc3000.deleteProfiles()) {
    Serial.println(F("Failed!"));
    while (1);
  }
  cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
  Serial.println(F("Connected!"));
  flash(3);
  Serial.println(F("Request DHCP"));
  while (!cc3000.checkDHCP()) {
    delay(100); // ToDo: Insert a DHCP timeout!
  }
  uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
  while (!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv)) {
    Serial.println(F("Unable to retrieve the IP Address!"));
    delay(100);
  }
  Serial.print(F("\nCC3000 IP Addr: "));
  cc3000.printIPdotsRev(ipAddress);
  //the following sets receiver to x.x.x.99 and assume cc3000 will never get exactly that IP itself
  ipAddress = cc3000.IP2U32(ipAddress >> 24 & 255, ipAddress >> 16 & 255, ipAddress >> 8 & 255, 99);
  Serial.print(F("\nReceiver IP Addr: "));
  cc3000.printIPdotsRev(ipAddress);
  client = cc3000.connectUDP(ipAddress, PORT);

  //--OSC message [/tk2, index, value]
  buf[0] = 47;   // /
  buf[1] = 116;  // t
  buf[2] = 107;  // k
  buf[3] = 50;   // 2
  buf[4] = 0;
  buf[5] = 0;
  buf[6] = 0;
  buf[7] = 0;
  buf[8] = 44;   // ,
  buf[9] = 105;  // i
  buf[10] = 0;
  buf[11] = 0;
  buf[12] = 0;   //msb - index
  buf[13] = 0;   //
  buf[14] = 0;   //
  buf[15] = 0;   //lsb - value
}

void loop(void) {
  byte val;

  //--analogue inputs
  for (byte i = 0; i < 13; i++) {
    setChan(i);
    delay(1);                //not sure if needed
    val = analogRead(A5) >> 2; //from 10 to 8 bits
    if (val != last[i]) {
      sendOsc(i, val);
      last[i] = val;
    }
  }

  //--digital inputs
  val = PINC & 0b00011111;
  if (val != last[13]) {
    sendOsc(13, val);
    last[13] = val;
  }

  //--ping
  if (millis() - time > PINGRATE) {
    sendOsc(127, 0);      //ping
    time = millis();
  }
}

void sendOsc(byte index, byte val) {
  buf[12] = index;
  buf[15] = val;
  if (cnt++ % 2 == 0) {   //toggle red led
    PORTD &= ~_BV(DDD7);
  }
  else {
    PORTD |= _BV(DDD7);
  }
  client.write(buf, sizeof(buf));
  delay(DELAY);
}

void setChan(byte index) {
  switch (index) {
    case 0:
      PORTD &= ~_BV(DDD2);        //low
      PORTD &= ~_BV(DDD4);        //low
      PORTD &= ~_BV(DDD5);        //low
      PORTD &= ~_BV(DDD6);        //low
      break;
    case 1:
      PORTD |= _BV(DDD2);    //high
      PORTD &= ~_BV(DDD4);        //low
      PORTD &= ~_BV(DDD5);        //low
      PORTD &= ~_BV(DDD6);        //low
      break;
    case 2:
      PORTD &= ~_BV(DDD2);        //low
      PORTD |= _BV(DDD4);    //high
      PORTD &= ~_BV(DDD5);        //low
      PORTD &= ~_BV(DDD6);        //low
      break;
    case 3:
      PORTD |= _BV(DDD2);    //high
      PORTD |= _BV(DDD4);    //high
      PORTD &= ~_BV(DDD5);        //low
      PORTD &= ~_BV(DDD6);        //low
      break;
    case 4:
      PORTD &= ~_BV(DDD2);        //low
      PORTD &= ~_BV(DDD4);        //low
      PORTD |= _BV(DDD5);    //high
      PORTD &= ~_BV(DDD6);        //low
      break;
    case 5:
      PORTD |= _BV(DDD2);    //high
      PORTD &= ~_BV(DDD4);        //low
      PORTD |= _BV(DDD5);    //high
      PORTD &= ~_BV(DDD6);        //low
      break;
    case 6:
      PORTD &= ~_BV(DDD2);        //low
      PORTD |= _BV(DDD4);    //high
      PORTD |= _BV(DDD5);    //high
      PORTD &= ~_BV(DDD6);        //low
      break;
    case 7:
      PORTD |= _BV(DDD2);    //high
      PORTD |= _BV(DDD4);    //high
      PORTD |= _BV(DDD5);    //high
      PORTD &= ~_BV(DDD6);        //low
      break;
    case 8:
      PORTD &= ~_BV(DDD2);        //low
      PORTD &= ~_BV(DDD4);        //low
      PORTD &= ~_BV(DDD5);        //low
      PORTD |= _BV(DDD6);    //high
      break;
    case 9:
      PORTD |= _BV(DDD2);    //high
      PORTD &= ~_BV(DDD4);        //low
      PORTD &= ~_BV(DDD5);        //low
      PORTD |= _BV(DDD6);    //high
      break;
    case 10:
      PORTD &= ~_BV(DDD2);        //low
      PORTD |= _BV(DDD4);    //high
      PORTD &= ~_BV(DDD5);        //low
      PORTD |= _BV(DDD6);    //high
      break;
    case 11:
      PORTD |= _BV(DDD2);    //high
      PORTD |= _BV(DDD4);    //high
      PORTD &= ~_BV(DDD5);        //low
      PORTD |= _BV(DDD6);    //high
      break;
    case 12:
      PORTD &= ~_BV(DDD2);        //low
      PORTD &= ~_BV(DDD4);        //low
      PORTD |= _BV(DDD5);    //high
      PORTD |= _BV(DDD6);    //high
      break;
  }
}
void flash(int num) {
  for(byte i= 0; i<num; i++) {
    digitalWrite(7, HIGH);
    delay(100);
    digitalWrite(7, LOW);
    delay(100);
  }
}
Attachments:
redThermoKontroll2-supercollider.zip
‹ redAlertLightp5 Tweets ›