Hey there!
My plan is to connect potmeters/spst pushbuttons to my Arduino Uno, to read these by Puredata Extended through SimpleMessageSystem/Firmata (on a Raspberry Pi, but writing and pre-testing happens on my Mac), and then to let Puredata send out DMX through a DmxSimple sketch. For this I have a Tinkerkit DMX shield.
I got everything to work separately, but I can't get to combine the different sketches.
To make my steps clear:
-I first tested to send DMX to a connected DMX light. I used the SerialToDmx sketch which is provided with the DmxSimple library. This is the sketch:
#include <DmxSimple.h>
void setup() {
Serial.begin(9600);
Serial.println("SerialToDmx ready");
Serial.println();
Serial.println("Syntax:");
Serial.println(" 123c : use DMX channel 123");
Serial.println(" 45w : set current channel to value 45");
}
int value = 0;
int channel;
void loop() {
int c;
while(!Serial.available());
c = Serial.read();
if ((c>='0') && (c<='9')) {
value = 10*value + c - '0';
} else {
if (c=='c') channel = value;
else if (c=='w') {
DmxSimple.write(channel, value);
Serial.println();
}
value = 0;
}
}
-I then tested to get input from potmeters/pushbuttons. This all works through either the SimpleAnalogFirmata and the SimpleDigitalFirmata sketches. (for some reason the StandardFirmata gave me problems, and the sketch is too much anyways for what I need) I combined these sketches without a problem too:
#include <Firmata.h>
//Digital
byte previousPIN[TOTAL_PORTS]; // PIN means PORT for input
byte previousPORT[TOTAL_PORTS];
//Analog
byte analogPin = 0;
//Digital
void outputPort(byte portNumber, byte portValue)
{
// only send the data when it changes, otherwise you get too many messages!
if (previousPIN[portNumber] != portValue) {
Firmata.sendDigitalPort(portNumber, portValue);
previousPIN[portNumber] = portValue;
}
}
void setPinModeCallback(byte pin, int mode) {
if (IS_PIN_DIGITAL(pin)) {
pinMode(PIN_TO_DIGITAL(pin), mode);
}
}
void digitalWriteCallback(byte port, int value)
{
byte i;
byte currentPinValue, previousPinValue;
if (port < TOTAL_PORTS && value != previousPORT[port]) {
for(i=0; i<8; i++) {
currentPinValue = (byte) value & (1 << i);
previousPinValue = previousPORT[port] & (1 << i);
if(currentPinValue != previousPinValue) {
digitalWrite(i + (port*8), currentPinValue);
}
}
previousPORT[port] = value;
}
}
//Analog
void analogWriteCallback(byte Apin, int Avalue)
{
if (IS_PIN_PWM(Apin)) {
pinMode(PIN_TO_DIGITAL(Apin), OUTPUT);
analogWrite(PIN_TO_PWM(Apin), Avalue);
}
}
void setup()
{
//Digital
Firmata.setFirmwareVersion(0, 1);
Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
Firmata.attach(SET_PIN_MODE, setPinModeCallback);
Firmata.begin(57600);
//Analog
Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
}
void loop()
{
//Digital
byte i;
for (i=0; i<TOTAL_PORTS; i++) {
outputPort(i, readPort(i, 0xff));
}
while(Firmata.available()) {
Firmata.processInput();
}
//Analog
while(Firmata.available()) {
Firmata.processInput();
}
// do one analogRead per loop, so if PC is sending a lot of
// analog write messages, we will only delay 1 analogRead
Firmata.sendAnalog(analogPin, analogRead(analogPin));
analogPin = analogPin + 1;
if (analogPin >= TOTAL_ANALOG_PINS) analogPin = 0;
}
This is what I got when I merged this Firmata sketch with the DMX sketch:
//Digital / Analog
#include <Firmata.h>
//DMX
#include <DmxSimple.h>
//Digital
byte previousPIN[TOTAL_PORTS]; // PIN means PORT for input
byte previousPORT[TOTAL_PORTS];
//Analog
byte analogPin = 0;
//Digital
void outputPort(byte portNumber, byte portValue)
{
// only send the data when it changes, otherwise you get too many messages!
if (previousPIN[portNumber] != portValue) {
Firmata.sendDigitalPort(portNumber, portValue);
previousPIN[portNumber] = portValue;
}
}
void setPinModeCallback(byte pin, int mode) {
if (IS_PIN_DIGITAL(pin)) {
pinMode(PIN_TO_DIGITAL(pin), mode);
}
}
void digitalWriteCallback(byte port, int Dvalue)
{
byte i;
byte currentPinValue, previousPinValue;
if (port < TOTAL_PORTS && Dvalue != previousPORT[port]) {
for(i=0; i<8; i++) {
currentPinValue = (byte) Dvalue & (1 << i);
previousPinValue = previousPORT[port] & (1 << i);
if(currentPinValue != previousPinValue) {
digitalWrite(i + (port*8), currentPinValue);
}
}
previousPORT[port] = Dvalue;
}
}
//Analog
void analogWriteCallback(byte Apin, int Avalue)
{
if (IS_PIN_PWM(Apin)) {
pinMode(PIN_TO_DIGITAL(Apin), OUTPUT);
analogWrite(PIN_TO_PWM(Apin), Avalue);
}
}
void setup()
{
//Digital
Firmata.setFirmwareVersion(0, 1);
Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
Firmata.attach(SET_PIN_MODE, setPinModeCallback);
Firmata.begin(57600);
//Analog
Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
//DMX
//Serial.begin(9600);
Serial.println("SerialToDmx ready");
Serial.println();
Serial.println("Syntax:");
Serial.println(" 123c : use DMX channel 123");
Serial.println(" 45w : set current channel to value 45");
}
//DMX
//int value = 0;
//int channel;
void loop()
{
//Digital
byte i;
for (i=0; i<TOTAL_PORTS; i++) { //now it reads digital pins starting at pin 0 right? Because DMX goes over pin 3.
outputPort(i, readPort(i, 0xff));
}
while(Firmata.available()) {
Firmata.processInput();
}
//Analog
while(Firmata.available()) {
Firmata.processInput();
}
// do one analogRead per loop, so if PC is sending a lot of
// analog write messages, we will only delay 1 analogRead
Firmata.sendAnalog(analogPin, analogRead(analogPin));
analogPin = analogPin + 1;
if (analogPin >= TOTAL_ANALOG_PINS) analogPin = 0;
//DMX
// int c;
// while(!Serial.available());
// c = Serial.read();
// if ((c>='0') && (c<='9')) {
// value = 10*value + c - '0';
// } else {
// if (c=='c') channel = value;
// else if (c=='w') {
// DmxSimple.write(channel, value);
// Serial.println();
// }
// value = 0;
// }
}
As you can see I made some of the DMX lines into comments using '//', because I was testing to see where the two sketches had problems. Right now as it is, I can get data from the Analog and Digital pins, but when I 'uncomment' more lines of the DMX sketch, my data will not be received anymore. I thought it had to do with Serial.begin(9600) and Firmata.begin(57600). As far as I understand that is the speed the devices are talking on the serial connection. This might give some problems. I also realized that both sketches are trying to use the same pins. As far as I understand DmxSimple comunicates to my DMX Shield over digital pin 3.
I then sought a solution in trying another Sketch/Library to read the pins for Pure Data. I found the SimpleMessageSystem library with the Arduino2PD sketch and Pure Data patch. This also worked perfect with my pots and buttons, this is the sketch:
#include <SimpleMessageSystem.h>
char firstChar;
char secondChar;
void setup()
{
Serial.begin(115200);
}
void loop()
{
if (messageBuild()) { // Checks to see if the message is complete
firstChar = messageGetChar(); { // Gets the first word as a character
if (firstChar = 'r') { // Checking for the character 'r'
secondChar = messageGetChar(); // Gets the next word as a character
if (firstChar = 'd') // The next character has to be 'd' to continue
messageSendChar('d'); // Echo what is being read
for (int i=0;i<=5;i++) {
messageSendInt(analogRead(i)); // Read analog pins 0 to 5
}
for (int m=2;m<=12;m++) {
messageSendInt(digitalRead(m)); // Read digital pins 2 to 12, 13 is onboard LED on Arduino NG
}
messageEnd(); // Terminate the message being sent
}
}
}
}
I thought this sketch had perfect capabilities to work together with the DmxSimple sketch, because here I can set to read the digital pins starting from 4 (it is reading here starting from pin 2), and also it uses the same boud rate in this sketch as the DMX sketch (although it advices to test higher rates later). But when I merged them together, it still won't work for both. (I will post the code of this merge in the next post, because otherwise this post exceeds the 9500 characters I can use)
I tried to read and understand the sketches, but the referred libraries seem so complicated, that with my limited programming knowledge, it's impossible for me to really understand what is happening.
Could anyone help me?