Pages: [1]   Go Down
Author Topic: Pd OSC ints > Processing > Arduino > shif  (Read 2392 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi peeps,

As my first ever forum post I find myself begging for help. I'm not much of a coder and I somehow have talked myself into creating a project that takes sound data from pd and passes it over tcp ip to a processing sketch and then to an arduino. The idea is to influence LED colours through sound and pass the LED's through an old school video feedback loop in an immersion dome.

I'm using the osc external for pd and am getting data into processing fine with the following code:

import oscP5.*;
import netP5.*;
import processing.serial.*;
 
OscP5 oscP5;
NetAddress myRemoteLocation;
int pitchInt;
Serial myPort;

void setup() {
 oscP5 = new OscP5(this,9997);
 println(Serial.list());
 myPort = new Serial(this, Serial.list()[0], 115200);
 myRemoteLocation = new NetAddress("127.0.0.1",9997);
}

void draw(){
  try {
  myPort.write(pitchInt);
  int ardCallback = myPort.read();
  println(ardCallback);
} catch (Exception e) {
  //do anything you want to handle the exception
  println("Unable to parse int");
}
}


/* incoming osc message are forwarded to the oscEvent method. */
void oscEvent(OscMessage theOscMessage) {
  pitchInt = theOscMessage.get(0).intValue();
}



I'm then trying to write the values over serial to my arduino using a premade shiftbrite sketch I've found online:

/* Ports and Pins
 
 Direct port access is much faster than digitalWrite.
 You must match the correct port and pin as shown in the table below.
 
 Arduino Pin        Port        Pin
 13 (SCK)           PORTB       5
 12 (MISO)          PORTB       4
 11 (MOSI)          PORTB       3
 10 (SS)            PORTB       2
 9                  PORTB       1
 8                  PORTB       0
 7                  PORTD       7
 6                  PORTD       6
 5                  PORTD       5
 4                  PORTD       4
 3                  PORTD       3
 2                  PORTD       2
 1 (TX)             PORTD       1
 0 (RX)             PORTD       0
 A5 (Analog)        PORTC       5
 A4 (Analog)        PORTC       4
 A3 (Analog)        PORTC       3
 A2 (Analog)        PORTC       2
 A1 (Analog)        PORTC       1
 A0 (Analog)        PORTC       0
 
 */
 
// Defines for use with Arduino functions
#define clockpin   13 // CL
#define enablepin  10 // BL
#define latchpin    9 // XL
#define datapin    11 // SI
 
// Defines for direct port access
#define CLKPORT PORTB
#define ENAPORT PORTB
#define LATPORT PORTB
#define DATPORT PORTB
#define CLKPIN  5
#define ENAPIN  2
#define LATPIN  1
#define DATPIN  3
 
// Variables for communication
unsigned long SB_CommandPacket;
int SB_CommandMode;
int SB_BlueCommand;
int SB_RedCommand;
int SB_GreenCommand;
 
// Define number of ShiftBrite modules
#define NumLEDs 1
 
// Create LED value storage array
int LEDChannels[NumLEDs][3] = {0};
 
// Set pins to outputs and initial states
void setup() {
  Serial.begin(115200);
  pinMode(datapin, OUTPUT);
  pinMode(latchpin, OUTPUT);
  pinMode(enablepin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  digitalWrite(latchpin, LOW);
  digitalWrite(enablepin, LOW);
  SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR1)|(0<<SPR0);
}
 
// Load values into SPI register
void SB_SendPacket() {
 
    if (SB_CommandMode == B01) {
     SB_RedCommand = 127;
     SB_GreenCommand = 110;
     SB_BlueCommand = 110;
    }
 
    SPDR = SB_CommandMode << 6 | SB_BlueCommand>>4;
    while(!(SPSR & (1<<SPIF)));
    SPDR = SB_BlueCommand<<4 | SB_RedCommand>>6;
    while(!(SPSR & (1<<SPIF)));
    SPDR = SB_RedCommand << 2 | SB_GreenCommand>>8;
    while(!(SPSR & (1<<SPIF)));
    SPDR = SB_GreenCommand;
    while(!(SPSR & (1<<SPIF)));
 
}
 
// Latch values into PWM registers
void SB_Latch() {
 
  delayMicroseconds(1);
  LATPORT += (1 << LATPIN);
  //ENAPORT += (1 << ENAPIN);
  delayMicroseconds(1);
  //ENAPORT &= ~(1 << ENAPIN);
  LATPORT &= ~(1 << LATPIN);
 
}
 
// Send all array values to chain
void WriteLEDArray() {
 
  SB_CommandMode = B00; // Write to PWM control registers
 
  for (int i = 0; i<NumLEDs; i++) {
    SB_RedCommand = LEDChannels
  • & 1023;
   SB_GreenCommand = LEDChannels[1] & 1023;
    SB_BlueCommand = LEDChannels[2] & 1023;
    SB_SendPacket();
  }
 
  SB_Latch();
 
  SB_CommandMode = B01; // Write to current control registers
 
  for (int z = 0; z < NumLEDs; z++) SB_SendPacket();  
 
  SB_Latch();
 
}
 
// Fade between two colors at specified interval
void fadeall(int rate, int fromred, int fromgreen, int fromblue, int tored, int togreen, int toblue) {
 
 for (int i = 0; i < 33; i++) {
 
     for (int j1 = 0; j1 < NumLEDs; j1++) {
       LEDChannels[j1][0] = (fromred * (32 - i) + tored * i)/32;
       LEDChannels[j1][1] = (fromgreen * (32 - i) + togreen * i)/32;
       LEDChannels[j1][2] = (fromblue * (32 - i) + toblue * i)/32;
     }
 
    WriteLEDArray();
    delay(rate);
 
   }  
}
 
void loop() {
 while (Serial.available() > 0) {
  int inByte = Serial.read();
  Serial.write(inByte);
  inByte = inByte *5;
  if (inByte > 0){
    fadeall(60,0,500,0,0,0,1023);
    delay(inByte);
    fadeall(60,0,0,1023,0,0,0);  
    delay(inByte);
  }
  else {
    
  }
 }
}




Due to the nature of this setup i'm finding it really hard to debug as the serial port is being used constantly. As my processing sketch is printing to the port I am having to process it on the arduino and then re-write it to the port and print it from processing :s

Can anyone identify any silly mistakes I am making?

Any help would be greatly appreciated smiley


Nick


« Last Edit: January 18, 2011, 07:20:23 am by NickJPM » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 640
Posts: 50331
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Can anyone identify any silly mistakes I am making?
Besides not telling us what problem(s) you are having, if any?

Quote
Due to the nature of this setup i'm finding it really hard to debug as the serial port is being used constantly. As my processing sketch is printing to the port I am having to process it on the arduino and then re-write it to the port and print it from processing :s
But, that works.

You could get a LCD to attach to the Arduino, and write debug data there...

You could avoid the issues with debugging by breaking the programming up into smaller pieces. Get Processing and Arduino to send data back and forth reliably. Then, extend the Arduino sketch to do something with the data. Then, extend the Processing sketch to send meaningful data.

Extend one sketch at a time. Then, any issues are with the new code...
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Paul,

Thanks for the quick reply... basically the inByte I am receiving in arduino doesn't seem to work in the conditional statements or as an integer parameter for the other functions.

Is the arduino code for reading incoming data correct?
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26496
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What about it 'doesn't seem to work'?
Could it be that you're overlowing your serial buffer because of all those delays?
Have you tried send commands singly, using the serial monitor instead of your Processing sketch?
« Last Edit: January 18, 2011, 08:14:44 am by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sending commands through the monitor works fine... What would be the best logical way of reading serial data in real time and then writing the incoming data on the fly?

Is anyone aware of how arduino interprets the port.write(int); method in processing... ie does it recognise the byte as an integer or do I have to convert it with atoi? Processing seems to do the conversion for me which I think is why I'm getting different results from the arduino?

Thanks again for the advice so far!
« Last Edit: January 18, 2011, 08:32:33 am by NickJPM » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 640
Posts: 50331
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is anyone aware of how arduino interprets the port.write(int); method in processing... ie does it recognise the byte as an integer or do I have to convert it with atoi?
Processing sends data as strings. You need, on the Arduino side, to collect all the characters for a value into an array, and pass that (NULL terminated) array to atoi to reconstruct the integer value.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Paul,

Thanks again for the point in the right direction! I think I am almost there... trying to adapt a bit of AWOL's code from another post to mine but it seems to be concatenating values through the serial monitor. if i type a 1 first its fine... if i then type 33 the next number is 13... then a 3 will pop up. Any ideas on where I'm going wrong?

Code:

char val [10];
int index = 0;

void loop() {
  long now = millis();
  if (Serial.available() > 0) {
    inByte = Serial.read();
    // if (now % 1000){
    val[index++] = inByte;
    val[index] = '\0';
    int a = atoi(val);
    Serial.println(a);
      if (a > 0 && a < 60){
        fadeall(50,1023,0,0,0,0,1023); //from red to blue
      }
      else if (a > 60){
        fadeall(50,0,0,1023,1023,0,0); //from blue to red
      }
      else {
      }
      if (inByte <= '0' || inByte >= '9') {
        index = 0;
      }
    a = 0;
    //Serial.flush();
    //  }
  }
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 640
Posts: 50331
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
if i type a 1 first its fine... if i then type 33 the next number is 13... then a 3 will pop up. Any ideas on where I'm going wrong?
You need some kind of end of packet marker. The Arduino needs to read all serial data available, on every pass through loop, not just one byte.

In addition, the Arduino should not be calling atoi until the end of packet marker arrives. When the end of packet marker arrives, do stuff with the serial data, and then re-initialize everything in preparation for the next packet.
Logged

SF Bay Area
Offline Offline
Edison Member
*
Karma: 11
Posts: 1244
Arduino Ninja
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I suggest the SSC "protocol". It's probably the absolute simplest possible, and seems to work well. A packet of data always starts with byte value of 255. All your other data must be less than 255; sacrificing that last bit seems worth the simplicity.

The processing logic is really easy. Look at the bytes as they come in; if you see 255, then reset an index counter and maybe set a flag that you're getting new data. From there, you can either wait for a known number of bytes, time out, or send another 255 to indicate end of transmission. You can put whatever you want in between. Set the first byte as a function type, or channel designator, etc.
Logged

Unique RGB LED Modules and Arduino shields: http://www.macetech.com/store

0
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi guys,

Firstly, Garet thank you for the SSC suggestion, I think that will do nicely as long as I can manipulate the data I'm receiving before passing it through to one of your shiftbrites (ie multiply the value by 100).

I have tried to implement the ssc protocol and can feel I am really close but cannot see where I am going wrong. Whenever I send for example "226" in the serial monitor I get the following:

colour = -1
I received: ÿ
this has an ASCII value of -1
Serial reset to: 0
colour = 54
I received: 6
this has an ASCII value of 54
Serial reset to: 0

So it's only seeing the 3rd byte I'm sending (I think this is supposed to happen?)

Arduino Code:

byte s = 0;
int colour = 0;
int SerialCount = 0;

void loop() {
  long now = millis();

  while (Serial.available() > 0) {
    byte s = Serial.read(); //1st byte received of message will be 255
    if (s == 255) {
      SerialCount = 0;
      byte s = Serial.read();
    }
    else if (s != 255 && SerialCount == 0) { //now read the colour value (expected 0-9)
      colour = Serial.read();
      SerialCount++;
      Serial.print("colour = ");
      //colour = colour * 100; //multiply the colour back up to usable number
      Serial.println(colour);

      fadeall(50,1023,0,0,1023,0,colour); //from red to a purple of somesort
      Serial.print("I received: ");
      Serial.println(colour, BYTE); //what byte value did I receive
      Serial.print("this has an ASCII value of ");
      Serial.println(colour,DEC); //what is this in ASCII format
    }
    if (SerialCount > 0 && SerialCount < 2){
    SerialCount = 0; //reset the counter
    }
    Serial.println("Serial reset to: ");
    Serial.print(SerialCount); //confirm it's been reset
  }
}

I did post something up earlier but after reading it it was a bit humiliating on my part! Unfortunately I can't seem to get over this last hurdle. Everyone's help is greatly appreciated and tbh I wouldn't have gotten this far without it smiley-grin I am trying to multiply that number by 100 but it always returns -100.

Nick
« Last Edit: January 20, 2011, 12:47:41 pm by NickJPM » Logged

Pages: [1]   Go Up
Jump to: