Show Posts
Pages: [1] 2
1  Forum 2005-2010 (read only) / Interfacing / Re: DMX woes... on: February 05, 2009, 09:46:56 am
Glad some people are using the code, even if they can't quite make it work yet...

I think your problem is that your Arduino uses an AtMega168 cpu and the code was written for an AtMega8. You've changed all of the register names to match your cpu, but you've missed the interrupt signal name.

I've just had a quick look at "wiring_serial.c", and it contains the following piece of code where the serial interrupt service routine is defined :

Code:
#if defined(__AVR_ATmega168__)
SIGNAL(SIG_USART_RECV)
#else
SIGNAL(SIG_UART_RECV)
#endif

I've had a look at your code, and you are still using SIGNAL(SIG_UART_RECV) which will only work with an AtMega8. If you change this to read SIGNAL(SIG_USART_RECV) your problem should be resolved.  smiley There is nothing wrong with the nested "else...if" statements, though feel free to re-write them if it will make you feel happier  smiley-wink

As to what use there is for receiving DMX, I am using this code to control two TLC5940 LED drivers which drive a 4 by 8 grid of LEDs. I've also made another version which controls 10 Piranha RGB LEDs, though I'm having a slight problem with the wiring at the moment...

Edit : Just had a look at the sn75176a datasheet and I noticed that you haven't connected the DE pin to ground. I use the MAX487 transceiver chip and its datasheet recommends that its DE pin is tied to ground if you are just recieving data. Might be worth trying on your setup.
2  Forum 2005-2010 (read only) / Interfacing / Re: DMX woes... on: October 05, 2008, 07:19:00 am
IT WORKS! YAY!!!

I turns out that I wasn't setting the baud rate correctly. Anyway, heres the working code :

Code:
// ********************* local definitions *********************
#define DMX_CHANNELS    (32)            //Define the number of DMX values to store

enum {IDLE, BREAK, STARTB, STARTADR};      //DMX states

uint8_t  gDmxState;
uint8_t  *gDmxPnt;
uint16_t DmxCount;

uint8_t  DmxField[DMX_CHANNELS];     //array of DMX vals (raw)
uint16_t DmxAddress;                   //start address

int ledPin = 13;                       // LED connected to digital pin 13

void setup()                           // run once, when the sketch starts
{
  // sets the digital pin as output
  pinMode(ledPin, OUTPUT);      
  
  // Disable interrupts
  cli();    
  
  // 250kbps baud - only works for 16MHz clock frequency. See the ATMega8 datasheet if you are using a different clock speed
  UBRRH = 0;
  UBRRL = 3;
      
  // enable rx and interrupt on complete reception of a byte
  UCSRB = (1<<RXEN)|(1<<RXCIE);
  UCSRC = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
      
  // Enable interrupts
  sei();

  gDmxState= IDLE;

  uint8_t i;
  for (i=0; i<DMX_CHANNELS; i++)
  {
    DmxField[i]= 0;
  }

  DmxAddress= 10;  //Set the base DMX address. Could use DIP switches for this.
}

void loop()                     // run over and over again
{
  if(DmxField[0] >=127)
  {
    digitalWrite(ledPin, HIGH);   // sets the LED on
  }
  else
  {
    digitalWrite(ledPin, LOW);    // sets the LED off
  }
}

// *************** DMX Reception ISR ****************
SIGNAL(SIG_UART_RECV)
{
uint8_t USARTstate= UCSRA;                              //get state
uint8_t DmxByte= UDR;                                    //get data
uint8_t DmxState= gDmxState;                              //just get once from SRAM!!!
 
if (USARTstate &(1<<FE))                              //check for break
      {
      UCSRA &= ~(1<<FE);                              //reset flag
      DmxCount= DmxAddress;                              //reset frame counter
      gDmxState= BREAK;
      }

else if (DmxState == BREAK)
      {
      if (DmxByte == 0)
            {
            gDmxState= STARTB;                        //normal start code detected
            gDmxPnt= ((uint8_t*)DmxField +1);
            }
      else gDmxState= IDLE;
      }
      
else if (DmxState == STARTB)
      {
      if (--DmxCount == 0)                              //start address reached?
            {
            gDmxState= STARTADR;
            DmxField[0]= DmxByte;
            }
      }

else if (DmxState == STARTADR)
      {
      uint8_t *DmxPnt;
      DmxPnt= gDmxPnt;
      *DmxPnt= DmxByte;
      if (++DmxPnt >= (DmxField +DMX_CHANNELS))             //all ch received?
            {
            gDmxState= IDLE;
            }
      else gDmxPnt= DmxPnt;
      }                                          
}



Many thanks to Hendrik Hoelscher for the original code, and to those who've helped me on this forum.

At the moment, this code only works on the ATMega8 CPU, not the ATMega168 as the register names are different. I don't have a 168-based Arduino to play with so if anyone wants to add to the code to make it work with the 168, be my guest. Also I think this might be worth putting into a separate library once it is made to work with the 168-based boards.
3  Forum 2005-2010 (read only) / Interfacing / Re: DMX woes... on: October 04, 2008, 10:45:44 pm
Unfortunately the code examples and tutorials are for sending DMX with an Arduino, not receiving it...
4  Forum 2005-2010 (read only) / Interfacing / DMX woes... on: October 04, 2008, 05:51:46 am
Hi

I am trying to adapt Hendrik Hoelschers DMX code which he created for the ATMega8515. His code can be found here : http://www.hoelscher-hi.de/hendrik/english/ressources.htm.

I have tried to port his code to my Arduino, which is just an ATMega8 I've put together on stripboard. I program it using a parallel port programmer, so the Rx and Tx pins are free. I've used a Maxim Max487 RS485 transceiver chip which I have successfully used on other DMX projects. It is wired up only to receive DMX and is hooked up to the Rx pin of my ATMega8.

Anyway, heres my version of the code. :

Code:
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>

// ********************* local definitions *********************
#define DMX_CHANNELS    (32)                        //use at least 2ch

enum {IDLE, BREAK, STARTB, STARTADR};                  //DMX states

  uint8_t  gDmxState;
  uint8_t  *gDmxPnt;
  uint16_t DmxCount;

  uint8_t  DmxField[DMX_CHANNELS]; //array of DMX vals (raw)
  uint16_t DmxAddress;                  //start address

int ledPin = 13;                // LED connected to digital pin 13

void setup()                    // run once, when the sketch starts
{
  // sets the digital pin as output
  pinMode(ledPin, OUTPUT);      
  
  // Disable interrupts
  cli();    
  
  // 250kbps baud
  UBRRH = 0;
  UBRRL = ((F_CPU /4000) - 1);
      
  // enable rx and interrupt on complete reception of a byte
  UCSRC |= (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
  UCSRB |= (1<<RXEN)|(1<<RXCIE);
      
  // Enable interrupts
  sei();

  gDmxState= IDLE;

  uint8_t i;
  for (i=0; i<DMX_CHANNELS; i++)
  {
    DmxField[i]= 0;
  }
  DmxAddress= 10;
  if (!(UCSRB &(1<<RXCIE)))                              //if receiver was disabled -> enable and wait for break
  {
    gDmxState= IDLE;
    UCSRB |= (1<<RXCIE);
  }
}

void loop()                     // run over and over again
{
  if(DmxField[0] >=127)
  {
    digitalWrite(ledPin, HIGH);   // sets the LED on
  }
  else
  {
    digitalWrite(ledPin, LOW);    // sets the LED off
  }
}

// *************** DMX Reception ISR ****************
ISR (UART_RX_vect)
{
uint8_t USARTstate= UCSRA;                                    //get state
uint8_t DmxByte= UDR;                                          //get data
uint8_t DmxState= gDmxState;                              //just get once from SRAM!!!
 
if (USARTstate &(1<<FE))                                    //check for break
      {
      UCSRA &= ~(1<<FE);                                          //reset flag
      DmxCount= DmxAddress;                                    //reset frame counter
      gDmxState= BREAK;
      }

else if (DmxState == BREAK)
      {
      if (DmxByte == 0)
            {
            gDmxState= STARTB;                                    //normal start code detected
            gDmxPnt= ((uint8_t*)DmxField +1);
            }
      else gDmxState= IDLE;
      }
      
else if (DmxState == STARTB)
      {
      if (--DmxCount == 0)                                    //start address reached?
            {
            gDmxState= STARTADR;
            DmxField[0]= DmxByte;
            }
      }

else if (DmxState == STARTADR)
      {
      uint8_t *DmxPnt;
      DmxPnt= gDmxPnt;
      *DmxPnt= DmxByte;
      if (++DmxPnt >= (DmxField +DMX_CHANNELS))       //all ch received?
            {
            gDmxState= IDLE;
            }
      else gDmxPnt= DmxPnt;
      }                                          
}

It just grabs 32 DMX values starting at 10. If DMX channel 10 goes over 127, the LED is turned on. At the moment though, nothing happens. I've tried turning the LED on only when the ISR() function is called, but it never is.  :-? My transceiver chip appears to be wired up correctly, so I guess the issue is with the code somewhere. Given that I am very much a beginner when it comes to coding on an Arduino I would appreciate it if any of you could give me pointers as to where I am going wrong.


Thanks


5  Forum 2005-2010 (read only) / Interfacing / Re: Maximum Serial Baud Rate on: February 25, 2009, 01:27:25 pm
If you have a look at the AtMega168 datasheet, on page 197 it would seem to suggest that with a 16MHz clock the serial port can handle 1Mbps.

I use the AtMega8 processor in the Arduino clones I build, and they have no problem using the serial port to receive DMX. DMX runs at 250,000 bps.

6  Forum 2005-2010 (read only) / Interfacing / Re: TLC5940 + high current on: April 03, 2009, 03:26:16 am
If you want to run multiple LEDs in series from each OUTx pin, this document from Texas Instruments might help. It gives details on using a MOSFET to accomodate higher LED supply voltages, and LEDs in series.
7  Forum 2005-2010 (read only) / Interfacing / Re: LEDs in series and forward voltages. on: April 03, 2009, 03:29:29 am
Hmmm.... some interesting ideas, but I think I'll re-design my LED arrays to have 3 in series with a resistor to limit the current. Many thanks for everyones help with this.
8  Forum 2005-2010 (read only) / Interfacing / Re: LEDs in series and forward voltages. on: April 01, 2009, 10:03:23 am
Actually I'm not that bothered if each LED gets less than 20mA. I already have a 12 volt power supply so I'd like to use if possible, but I've already built a test board with sets of four LEDs in series, so it seems I have three options.

First off, I could keep the power supply I've already got, but re-design/re-build the boards to include resistors.

The second option is to get a different power supply (15 volt laptop psu?) and some resistors to my boards.

The third option would be to keep both the boards and power supply, and find some way of limiting the current.

I'd like to go with either the second or preferably the third option. Its easy enough to add a few resistors to my boards though I'd rather not have to redsign them from scratch, which is what the first option would entail.

If I wanted to keep my power supply, and keep my LEDs in sets of four what is the maximum current I could reasonably expect to give them? I'm guessing that running them at less than their maximum current will give them an easier/longer life.

9  Forum 2005-2010 (read only) / Interfacing / Re: LEDs in series and forward voltages. on: April 01, 2009, 09:29:33 am
Many thanks for all your replies. However a question still remains. When working out the resistor to limit the curent do I use the upper or lower limit of the forward voltage in the equation? The datasheet gives the forward voltage as anywhere between 3 volts and 3.6 volts. If I use 3 volts, since the supply voltage is 12 volts and the LED current 20mA I get ((12-(3 LEDs x 3 volts))/0.02=150 Ohms. But if the forward voltage is taken to be 3.6 volts I get ((12-(3 LEDs x 3.6 volts))/0.02=60 Ohms.
10  Forum 2005-2010 (read only) / Interfacing / Re: LEDs in series and forward voltages. on: April 01, 2009, 08:03:41 am
Quote
What's the problem with using a resistor in this case?
No problem at all. I was just curious as to whether I needed one or not. My understanding of the usual LED resistor equation led me to beleive that if the forward and supply voltages were the same then no resistor would be necessary.

Since I do need a resistor, given that the datasheet gives the forward voltage as anywhere between 3 volts and 3.6 volts which value should I use when working out the resistor value? If I use 3 volts, since the supply voltage is 12 volts and the LED current 20mA I get ((12-(3 LEDs x 3 volts))/0.02=150 Ohms. But if the forward voltage is taken to be 3.6 volts I get ((12-(3 LEDs x 3.6 volts))/0.02=60 Ohms.
11  Forum 2005-2010 (read only) / Interfacing / LEDs in series and forward voltages. on: April 01, 2009, 04:29:45 am
I am currently building an LED array. I have a 12 volt switch-mode power supply which I would like to use to power my LEDs. My LEDs have a forward voltage of between 3.0 and 3.6 volts (according to the datasheet), and require 20mA. If I run my LEDs in series in strings of four, do I need a resistor since the combined forward voltage of four LEDs should be 12-14.4 volts?

I have previously used the "(Supply voltage- forward voltage)/ LED current" equation to calculate resistor values, but the "(Supply voltage- forward voltage)" part seems to suggest that if the supply voltage equals the forward voltage then no resistor is needed. Is this right?

I know that if the supply voltage equals the forward voltage and current is not limited, if the supply voltage increases only slightly then the current drawn by the LED increases very rapidly until the LED fails. But what happens if we go the other way? If the supply voltage is less than the forward voltage what happens to the LED and its current consumption?

Will I be OK using my 12 volt power supply and not having resistors to limit the current (since the usual equation for working out resistor values would suggest one is not needed), or should I get a higher-voltage supply (maybe a 15 volt laptop psu?) and add resistors to each string of four LEDs, or should I keep my 12 volt psu and add low-value resistors (maybe 1 ohm)??
12  Forum 2005-2010 (read only) / Interfacing / Re: Interfacing RGB LED with Rotary Switches on: February 05, 2009, 10:44:24 am
You could use one of these, but it won't be cheap....
13  Forum 2005-2010 (read only) / Interfacing / Re: Interfacing RGB LED with Rotary Switches on: February 05, 2009, 10:04:07 am
I think you are getting confused. Rotary switches are digital devices and don't need to be connected to an analogue input. They are often Binary Coded Decimal (BCD for short) switches which have ten selectable positions. The outputs from the switch would go to four digital inputs and would be set as follows :

Switch poition 0 = 0 0 0 0
Switch poition 1 = 0 0 0 1
Switch poition 2 = 0 0 1 0
Switch poition 3 = 0 0 1 1
                  .
                  .
                  .
Switch poition 9 = 1 0 0 1

For your application if you can't find 6-way switches (and you do mean 6-way, not 6-turn don't you?) just ignore any input higher than 6, or have some way of telling the user that the input is invalid.




14  Forum 2005-2010 (read only) / Interfacing / Re: receive form rs485 bus on: February 11, 2009, 01:50:10 pm
If you want to receive DMX have a look at this topic. Theres code for both AtMeg8 and AtMega168 cpus.
15  Forum 2005-2010 (read only) / Interfacing / Re: Probably simple transistor question on: February 06, 2009, 12:46:57 pm
Just a quick note about the TLC5940. Although it says in the datasheet that you can 120ma per channel, you can't have all 16 channels at 120ma at the same time! I found this out the hard way by destroying a few chips before I found the solution.

Theres a calculation in the datasheet which you can use to work out how much power you will disspate depending on how many channels are on, what their current is limited to, etc. I worked out that 25ma per channel at 5 volts was about as much as I could safely use if all channels were on at the same time, but I limit the current to 20ma with a 2k resistor between IRef and ground. I don't think that you will be able to use the TLC to limit the current if you are using transistors to switch your LEDs on and off.
Pages: [1] 2