Hello,
Erik thanks for a great board!
I'm working on a project and hit a block. I just dont yet understand enough about the arduino environment to figure it out.
Im working on a DMX lighting controller as a volunteer effort for a local youth theatre group.
Its a PS2 mouse based controller with a couple slide potentiometers.
Here's a little background on where I'm at:
breadboard
wiring
ps2 mouse
SN75176BP (rs486 chip for the DMX output)
The DMX circuit, PS2 interface to the input pins, and the poteniometer are all working well.
Aside from smoothing the slide values which I think needs a good enough bit level even at the suggested 10K range, might still be some interference , the breadboard wiring loops might still be picking up noise. All that I'll get sorted out.
I started out on a rev3 Arduino UNO and all the various parts worked well separately and tested.
I got to the point of working out all the PS2 init code and got all the X Y X movements and slider values to send solid value to Serial.print. Aside from the smoothing that either 12 bits resolution will fix or better physical analog input.
At this point I'd tested the DMX layer by sending solid DMX data from the UNO to another DMX USB receiver and was seeing output.
Now I needed to put all the parts together...
loop() locks up so I decided it was time to grab the Digix and test the resolution at 12 bit... Helped! Not perfect but much better...
but when I but all the code together and have the PS2 , analog sliders, serial.prints and DMX output all together, loop consistently locks up on the second loop.
At this point as many of you more experienced Arduino developers surely know....
None of the libraries that expected specific boards worked
I'm deep into trying to just force the library into the future trying to learning enough about the various boards to help myself through __SAM3XA__ __AVR_ATmega...__ details to see if I can get the code to compile
Brute force to jump start what I suspect is going to be a long learning curve, but I'll get there...
I want to thank erik for a quick tip __SAM3XA__ the old libraries many arent Due aware
the DmxMaster library no only not being Due aware also blocks interrupts... DMX timing is very critical and the library calls cli() sei() which werent defined with the board type set to DigiX, I hopefully took care of that by simply changing code to NoInterrupt() and interrupt()
I had to commment out :
//#include <avr/io.h>
//#include <util/delay.h>
I'm still trying to find them. I installed 1.5.4, so maybe they are only in the old version of the arduino IDE...
my C isnt that string but is going to get better by spring time, I have a good time line , this volunteer project isnt urgent.
My electronics isn't strong, but good enough to get by and google my why through to making progress.
At the moment I have a controller and code issue.
I enabled the check boxes to show the compile and error details. Not sre if there are others but this seems to output enough to post
I suspect __SAM3XA__ is going to need to make an appearance in the code along with what I'm going to have to learn about the chipset changes...
So, where do I begin?
Thanks,
Paul
C:\Program Files\Arduino/hardware/tools/g++_arm_none_eabi/bin/arm-none-eabi-g++ -c -g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=154 -DARDUINO_SAM_DIGIX -DARDUINO_ARCH_SAM -D__SAM3X8E__ -mthumb -DUSB_PID=0x078A -DUSB_VID=0x16D0 -DUSBCON -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\system/libsam -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\system/CMSIS/CMSIS/Include/ -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\system/CMSIS/Device/ATMEL/ -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\cores\digix -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\variants\digix -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\PS2 -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\DmxMaster C:\DOCUME~1\RENSSE~1\LOCALS~1\Temp\build6414767374750799333.tmp\DMXFollowSpotController.cpp -o C:\DOCUME~1\RENSSE~1\LOCALS~1\Temp\build6414767374750799333.tmp\DMXFollowSpotController.cpp.o
C:\Program Files\Arduino/hardware/tools/g++_arm_none_eabi/bin/arm-none-eabi-g++ -c -g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=154 -DARDUINO_SAM_DIGIX -DARDUINO_ARCH_SAM -D__SAM3X8E__ -mthumb -DUSB_PID=0x078A -DUSB_VID=0x16D0 -DUSBCON -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\system/libsam -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\system/CMSIS/CMSIS/Include/ -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\system/CMSIS/Device/ATMEL/ -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\cores\digix -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\variants\digix -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\PS2 -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\DmxMaster -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\PS2\utility C:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\PS2\ps2.cpp -o C:\DOCUME~1\RENSSE~1\LOCALS~1\Temp\build6414767374750799333.tmp\PS2\ps2.cpp.o
C:\Program Files\Arduino/hardware/tools/g++_arm_none_eabi/bin/arm-none-eabi-g++ -c -g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=154 -DARDUINO_SAM_DIGIX -DARDUINO_ARCH_SAM -D__SAM3X8E__ -mthumb -DUSB_PID=0x078A -DUSB_VID=0x16D0 -DUSBCON -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\system/libsam -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\system/CMSIS/CMSIS/Include/ -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\system/CMSIS/Device/ATMEL/ -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\cores\digix -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\hardware\ardunio\sam\variants\digix -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\PS2 -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\DmxMaster -IC:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\DmxMaster\utility C:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\DmxMaster\DmxMaster.cpp -o C:\DOCUME~1\RENSSE~1\LOCALS~1\Temp\build6414767374750799333.tmp\DmxMaster\DmxMaster.cpp.o
C:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\DmxMaster\DmxMaster.cpp:150: error: macro "ISR" passed 2 arguments, but takes just 1
C:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\DmxMaster\DmxMaster.cpp: In function 'void dmxBegin()':
C:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\DmxMaster\DmxMaster.cpp:64: error: cannot convert 'volatile RwReg*' to 'volatile uint8_t*' in assignment
C:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\DmxMaster\DmxMaster.cpp: At global scope:
C:\Documents and Settings\Rensselaer Student\My Documents\Arduino\libraries\DmxMaster\DmxMaster.cpp:152: error: expected constructor, destructor, or type conversion before '{' token
***DmxMaster.h***
/**
* DmxMaster - A simple interface to DMX.
*
* Copyright (c) 2008-2009 Peter Knight, Tinker.it! All rights reserved.
*/
#ifndef DmxMaster_h
#define DmxMaster_h
#include <inttypes.h>
#if RAMEND <= 0x4FF
#define DMX_SIZE 128
#else
#define DMX_SIZE 512
#endif
class DmxMasterClass
{
public:
void maxChannel(int);
void write(int, uint8_t);
void usePin(uint8_t);
};
extern DmxMasterClass DmxMaster;
#endif
***DmxMaster.cpp***
/**
* DmxMaster - A simple interface to DMX.
*
* Copyright (c) 2008-2009 Peter Knight, Tinker.it! All rights reserved.
*/
//#include <avr/io.h>
#include <avr/interrupt.h>
//#include <util/delay.h>
#include "pins_arduino.h"
#include "Arduino.h"
#include "DmxMaster.h"
/** dmxBuffer contains a software copy of all the DMX channels.
*/
volatile uint8_t dmxBuffer[DMX_SIZE];
static uint16_t dmxMax = 16; /* Default to sending the first 16 channels */
static uint8_t dmxStarted = 0;
static uint16_t dmxState = 0;
static volatile uint8_t *dmxPort;
static uint8_t dmxBit = 0;
static uint8_t dmxPin = 3; // Defaults to output on pin 3 to support Tinker.it! DMX shield
void dmxBegin();
void dmxEnd();
void dmxSendByte(volatile uint8_t);
void dmxWrite(int,uint8_t);
void dmxMaxChannel(int);
/* TIMER2 has a different register mapping on the ATmega8.
* The modern chips (168, 328P, 1280) use identical mappings.
*/
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega1280__)
#define TIMER2_INTERRUPT_ENABLE() TIMSK2 |= _BV(TOIE2)
#define TIMER2_INTERRUPT_DISABLE() TIMSK2 &= ~_BV(TOIE2)
#elif defined(__AVR_ATmega32U4__)
#define TIMER2_INTERRUPT_ENABLE() TIMSK3 |= _BV(TOIE3)
#define TIMER2_INTERRUPT_DISABLE() TIMSK3 &= ~_BV(TOIE3)
#elif defined(__AVR_ATmega8__)
#define TIMER2_INTERRUPT_ENABLE() TIMSK |= _BV(TOIE2)
#define TIMER2_INTERRUPT_DISABLE() TIMSK &= ~_BV(TOIE2)
#else
#define TIMER2_INTERRUPT_ENABLE()
#define TIMER2_INTERRUPT_DISABLE()
/* Produce an appropriate message to aid error reporting on nonstandard
* platforms such as Teensy.
*/
#warning "DmxMaster does not support this CPU"
#endif
/** Initialise the DMX engine
*/
void dmxBegin()
{
dmxStarted = 1;
#ifdef __AVR_ATmega32U4__
TCCR3A = _BV(WGM30);
TCCR3B = _BV(CS31) | _BV(CS30);
#endif
// Set up port pointers for interrupt routine
dmxPort = portOutputRegister(digitalPinToPort(dmxPin));
dmxBit = digitalPinToBitMask(dmxPin);
// Set DMX pin to output
pinMode(dmxPin,OUTPUT);
// Initialise DMX frame interrupt
//
// Presume Arduino has already set Timer2 to 64 prescaler,
// Phase correct PWM mode
// So the overflow triggers every 64*510 clock cycles
// Which is 510 DMX bit periods at 16MHz,
// 255 DMX bit periods at 8MHz,
// 637 DMX bit periods at 20MHz
TIMER2_INTERRUPT_ENABLE();
}
/** Stop the DMX engine
* Turns off the DMX interrupt routine
*/
void dmxEnd()
{
TIMER2_INTERRUPT_DISABLE();
dmxStarted = 0;
dmxMax = 0;
}
/** Transmit a complete DMX byte
* We have no serial port for DMX, so everything is timed using an exact
* number of instruction cycles.
*
* Really suggest you don't touch this function.
*/
void dmxSendByte(volatile uint8_t value)
{
uint8_t bitCount, delCount;
__asm__ volatile (
"cli\n"
"ld __tmp_reg__,%a[dmxPort]\n"
"and __tmp_reg__,%[outMask]\n"
"st %a[dmxPort],__tmp_reg__\n"
"ldi %[bitCount],11\n" // 11 bit intervals per transmitted byte
"rjmp bitLoop%=\n" // Delay 2 clock cycles.
"bitLoop%=:\n"\
"ldi %[delCount],%[delCountVal]\n"
"delLoop%=:\n"
"nop\n"
"dec %[delCount]\n"
"brne delLoop%=\n"
"ld __tmp_reg__,%a[dmxPort]\n"
"and __tmp_reg__,%[outMask]\n"
"sec\n"
"ror %[value]\n"
"brcc sendzero%=\n"
"or __tmp_reg__,%[outBit]\n"
"sendzero%=:\n"
"st %a[dmxPort],__tmp_reg__\n"
"dec %[bitCount]\n"
"brne bitLoop%=\n"
"sei\n"
:
[bitCount] "=&d" (bitCount),
[delCount] "=&d" (delCount)
:
[dmxPort] "e" (dmxPort),
[outMask] "r" (~dmxBit),
[outBit] "r" (dmxBit),
[delCountVal] "M" (F_CPU/1000000-3),
[value] "r" (value)
);
}
/** DmxMaster interrupt routine
* Transmit a chunk of DMX signal every timer overflow event.
*
* The full DMX transmission takes too long, but some aspects of DMX timing
* are flexible. This routine chunks the DMX signal, only sending as much as
* it's time budget will allow.
*
* This interrupt routine runs with interrupts enabled most of the time.
* With extremely heavy interrupt loads, it could conceivably interrupt its
* own routine, so the TIMER2 interrupt is disabled for the duration of
* the service routine.
*/
#ifdef __AVR_ATmega32U4__
ISR(TIMER3_OVF_vect,ISR_NOBLOCK)
#else
ISR(TIMER2_OVF_vect,ISR_NOBLOCK)
#endif
{
// Prevent this interrupt running recursively
TIMER2_INTERRUPT_DISABLE();
uint16_t bitsLeft = F_CPU / 31372; // DMX Bit periods per timer tick
bitsLeft >>=2; // 25% CPU usage
while (1) {
if (dmxState == 0) {
// Next thing to send is reset pulse and start code
// which takes 35 bit periods
uint8_t i;
if (bitsLeft < 35) break;
bitsLeft-=35;
*dmxPort &= ~dmxBit;
for (i=0; i<11; i++) _delay_us(

;
*dmxPort |= dmxBit;
_delay_us(

;
dmxSendByte(0);
} else {
// Now send a channel which takes 11 bit periods
if (bitsLeft < 11) break;
bitsLeft-=11;
dmxSendByte(dmxBuffer[dmxState-1]);
}
// Successfully completed that stage - move state machine forward
dmxState++;
if (dmxState > dmxMax) {
dmxState = 0; // Send next frame
break;
}
}
// Enable interrupts for the next transmission chunk
TIMER2_INTERRUPT_ENABLE();
}
void dmxWrite(int channel, uint8_t value) {
if (!dmxStarted) dmxBegin();
if ((channel > 0) && (channel <= DMX_SIZE)) {
if (value<0) value=0;
if (value>255) value=255;
dmxMax = max((unsigned)channel, dmxMax);
dmxBuffer[channel-1] = value;
}
}
void dmxMaxChannel(int channel) {
if (channel <=0) {
// End DMX transmission
dmxEnd();
dmxMax = 0;
} else {
dmxMax = min(channel, DMX_SIZE);
if (!dmxStarted) dmxBegin();
}
}
/* C++ wrapper */
/** Set output pin
* @param pin Output digital pin to use
*/
void DmxMasterClass::usePin(uint8_t pin) {
dmxPin = pin;
if (dmxStarted && (pin != dmxPin)) {
dmxEnd();
dmxBegin();
}
}
/** Set DMX maximum channel
* @param channel The highest DMX channel to use
*/
void DmxMasterClass::maxChannel(int channel) {
dmxMaxChannel(channel);
}
/** Write to a DMX channel
* @param address DMX address in the range 1 - 512
*/
void DmxMasterClass::write(int address, uint8_t value)
{
dmxWrite(address, value);
}
DmxMasterClass DmxMaster;