Pages: [1]   Go Down
Author Topic: Serial data to analog synthesizer..  (Read 1298 times)
0 Members and 1 Guest are viewing this topic.
Denmark
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am currently working on a project that has given me a rough time.

I need to establish a serial connection to transmit from Arduino to and old Roland Juno-60 synthesizer. The problem is, that my serial data seems to match exactly the "DCB"-protocol specified by the synth manual (31250 baud, separate clock signal, 1 start bit, 8 data bits, LSB first, odd parity, 2 stop bits, logic HIGH=0v, LOW=5v), but it doesn't work. It is supposed to make the synth play some notes, but nothing is happening..

The sketch I've written is based on a timer interrupt to generate a 31250hz clock signal on dPin 3, and standard Serial.write() for the data transmission.
The wierd thing is, that I have a previous sketch using a modified shiftOut()-function (to control the clock speed) that kinda works, even though the clock signal is quite unstable, oscillating between ~30k baud and 35k baud. This sketch actually triggers the synth, though the bytes recieved are by no means correct, and is quite impossible to control. However, it DOES trigger the synth, which I find a tad weird..

I've tried all sorts of workaraounds, but the only possible solution I can think of is, that the data signal from my tx-pin is perhaps not strong enough for TTL, when running it through a NOT-gate before it is send to the synth. In the "shiftOut"-sketch, the data signal is generated on dPins with digitalWrite() and is not inverted, and I figured that the solutions lies somewhere in this..

I'm not too bright in analogue electronics and the specifics of TTL, but could it be that the not gate (real basic made with two 10k resistors and an M2222 NPN) somehow make the data signal, voltage or current too weak?

NOT-gate diagram:


Please help..

/Mikkel

By the way I have some LogicSniffer files and screendumps from both sketches, and from a readout from the synth (which shows the "real life" data stream, clock, etc.) that I could post if necessary..
« Last Edit: June 26, 2013, 07:59:55 am by mikkelb » Logged

Denmark
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thought some code might help.. smiley


The "full implementation" with steady clock and Serial.write():

Code:
/*

 Firstly the timers are set up to bang out a clock signal of 31250HZ on pin 3.
 Followingly serial data is sent. Data bits must be inverted (LOW=5v, HIGH=0v) before sending them to DCB.
 
 Serial Data Stream for DCB:
 Using the SERIAL_8o2 parameter, the Arduino UART sends out the following:
 1 Start bit (LOW)
 8 Data bits (LSB first)
 1 Parity bit (Odd)
 2 Stop bits (HIGH)
 
 
 */

// Timer reload value, globally available
unsigned int tcnt2;

// Toggle HIGH or LOW digital write
int toggle1 = 0;

// Keep track of when each pin needs to be switched
int count1 = 0;

// Clock Output Pin
#define CLOCK_PIN 3
#define BUSY_PIN 4



void setup()
{
  //31250 Baud, Odd parity, 2 stop bits. (Juno accepts faulty parity bits)
  Serial.begin(31250,SERIAL_8O2);

  // First disable the timer overflow interrupt
  TIMSK2 &= ~(1<<TOIE2);

  // Configure timer2 in normal mode (no PWM)
  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
  TCCR2B &= ~(1<<WGM22);

  // Select clock source: internal I/O clock
  ASSR &= ~(1<<AS2);

  // Disable Compare Match A interrupt (only overflow)
  TIMSK2 &= ~(1<<OCIE2A);

  // Configure the prescaler to CPU clock divided by 128
  TCCR2B |= (1<<CS22)  | (1<<CS20); // Set bits
  TCCR2B &= ~(1<<CS21);             // Clear bit

  tcnt2 = 254; //31250Hz clock

  // Finally load end enable the timer
  TCNT2 = tcnt2;
  TIMSK2 |= (1<<TOIE2);

  //Configure I/O Pin Directions
  pinMode(CLOCK_PIN,OUTPUT);
  pinMode(BUSY_PIN,OUTPUT);

}

ISR(TIMER2_OVF_vect) {
  // Reload the timer
  TCNT2 = tcnt2;

  count1++;

  if (count1 == 1)
  {
    digitalWrite(CLOCK_PIN, toggle1 == 0 ? HIGH : LOW);
    toggle1 = ~toggle1;
    count1 = 0;
  }
}

void loop()
{
    digitalWrite(BUSY_PIN,HIGH);  //  Busy/Latch
    Serial.write(0xFE);  //Start Code
    Serial.write(0xAF);  //Play F#
    Serial.write(0xAA);  //Play G
    Serial.write(0xAB);  //Play G#
    Serial.write(0xAC);  //Play A
    Serial.write(0xAD);  //Play A#
    Serial.write(0xAE);  //Play B
    digitalWrite(BUSY_PIN,LOW); 
}

Next, the "fualty but working" version using shiftOut()
Code:
uint8_t dataPin = 8;
uint8_t clockPin = 3;
uint8_t latchPin = 4;

//Custom shiftOut-function

void shiftOutX(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, int val, uint8_t bits = 8)
{
  uint8_t i;
  for (i = 0; i < bits; i++)  {
    if (bitOrder == LSBFIRST)
      digitalWrite(dataPin, !!(val & (1 << i)));
    else   
      digitalWrite(dataPin, !!(val & (1 << ((bits - 1 - i)))));
    digitalWrite(clockPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(clockPin, LOW);
    delayMicroseconds(6);   
  }
}

void setup() {
  pinMode(dataPin,OUTPUT);
  pinMode(latchPin,OUTPUT);
  pinMode(clockPin,OUTPUT);

}

void loop() {
  // NB! Invert data bits
dcbWrite(~0xFE);

dcbWrite(~0xAA);
dcbWrite(~0xAB);
dcbWrite(~0xAC);
dcbWrite(~0xAD);
dcbWrite(~0xAE);
dcbWrite(~0xAF);

//delay(100);

dcbWrite(~0xFE);

dcbWrite(~0x2A);
dcbWrite(~0x2B);
dcbWrite(~0x2C);
dcbWrite(~0x2D);
dcbWrite(~0x2E);
dcbWrite(~0x2F);

}

void dcbWrite(byte data){
  digitalWrite(latchPin,HIGH);
  shiftOutX(dataPin,clockPin,LSBFIRST,0b1,1);    //Start
  shiftOutX(dataPin,clockPin,LSBFIRST,data,8);  //Data
  shiftOutX(dataPin,clockPin,LSBFIRST,0b1,1);    //Parity
  shiftOutX(dataPin,clockPin,LSBFIRST,0b0,10);    //Stop (rammer F# når den står til 10)

}
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


didn't the Hardware Serial not receive correctly on 31250 ?
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Edison Member
*
Karma: 32
Posts: 1388
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This sounds like an early midi precursor. (The 31250 baud is a clue) Is it supposed to be optically isolated?
Logged

Offline Offline
Edison Member
*
Karma: 32
Posts: 1388
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I also do not see how you can keep your clock and serial bytes in sync. You might need an Oscope to verify things are working as you plan.
Logged

Denmark
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks!

@robtillaart
No.. Something comes through, though but it's a line of chaotic notes, and definitly not the ones intended. I even got it to play random notes by just continously sending 0xFE, which is not supposed to trigger anything.
My guess is that the clock signal of the hardware serial sketch is so unstable, that it triggers the data bits at more or less random times, and thereby sending out pseudo-random data, which is probably bound to trigger something..

Anyway, the question is not so much why the hardware serial is acting weird, but more why the software serial is not working..

@KeithRB
Yeah, it's called DCB, and were used prorietarily by Roland in the early 80's just before MIDI was introduced. Well I checked the schematic of a JSQ-60 (DCB-sequencer) and it doesn't seem like it needs optocouling.
« Last Edit: June 26, 2013, 09:51:13 am by mikkelb » Logged

Denmark
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I also do not see how you can keep your clock and serial bytes in sync. You might need an Oscope to verify things are working as you plan.

I've been using OpenLogicSnigger to check the timing, and it should be in sync..

Software serial DCB output


Real DCB output (from a Juno 60)


Hardware serial DCB output
Logged

Denmark
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Could it be, that the "real" output sends a few additional 0's after the stop bits, and the software serial doesn't? And if so, is there any way to send 3-5, 0's on the tx pin, without start bits and parity? I tried a small delayMicroseconds(), but it also stops the clock signal..
Logged

Pages: [1]   Go Up
Jump to: