User Tools

Site Tools


projects:dmx_switch_box:home

DMX switch box

~~META:description abstract=8 channels simple DMX switch box~~

A low cost 8 channels DMX switch box.

Features

  • None other than switching stuff on and off on request :)

Electronics

schematic.svg

Source code

main.c
/**
 * @defgroup I2C slave DMX TX node
 * @type firmware
 * @file main.c
 * @author Etienne Meleard <etienne@yent.eu>
 * @creation 2015-06-16
 * @tabsize 4
 * @mcu ATMEGA8A
 * @fcpu 16MHz
*/
 
 
//============================ WARNING ===============================//
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
//                                                                    //
// Fuses must be like SUT1 = 1, SUT0 = 1, CKSEL3 = 1, CKSEL2 = 1,     //
// CKSEL1 = 1 and CKSEL0 = 0 to ensure using the crystal as clock     //
// (otherwise it uses the 8MHz internal clock), full swing mode is    //
// mandatory to acheive 16MHz operation.                               //
//                                                                    //
// CKDIV8 fuse must not be set to avoid clock frequency divided by 8  //
//                                                                    //
// Fuse set or = 1 means checked in ponyprog                          //
//                                                                    //
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
//====================================================================//
 
 
// ================= Fuses ================= //
 
/*FUSES = { // No success writing fuse this way, command line below ...
    .low = (FUSE_SUT1 & FUSE_SUT0 & FUSE_CKSEL3),
    .high = HFUSE_DEFAULT,
    .extended = EFUSE_DEFAULT,
};*/
 
// Run
// avrdude -c usbasp -p m8 -U lfuse:w:0xfe:m -U hfuse:w:0xd1:m -B250
// at first (-F may be needed)
 
 
// ================ Includes =============== //
 
#include <avr/io.h>
#include <sup_avr/io2.h>
#include <avr/interrupt.h>
#include <util/delay.h>
 
 
// ================ Pinouts ================ //
 
#define LED         Bit(PORTD).bit7
 
#define RX          Bit(PIND).bit0
#define RX_COMPLETE SIG_UART_RECV
#define RX_TIMER    TCNT0
 
#define TX          Bit(PORTD).bit1
#define TX_COMPLETE SIG_UART_TRANS
 
#define BREAK_LEN   22
#define MAB_LEN     2
 
#define CH_1       Bit(PORTD).bit5
#define CH_2       Bit(PORTD).bit6
#define CH_3       Bit(PORTD).bit7
#define CH_4       Bit(PORTB).bit0
#define CH_5       Bit(PORTB).bit1
#define CH_6       Bit(PORTB).bit2
#define CH_7       Bit(PORTB).bit3
#define CH_8       Bit(PORTB).bit4
 
// ================ Macros ================= //
 
#define BLINK       LED=1; _delay_ms(150); LED=0; _delay_ms(150)
#define PULSE10     LED=1; _delay_us(10); LED=0; _delay_us(10)
#define PULSE5      LED=1; _delay_us(5); LED=0; _delay_us(5)
#define PULSE3      LED=1; _delay_us(3); LED=0; _delay_us(3)
#define PULSE1      LED=1; _delay_us(1); LED=0; _delay_us(1)
 
#define MAX_TIME_WITHOUT_START  10000
 
// ================ Globals ================ //
 
volatile uint8_t receiving = 0;
volatile uint16_t received = 0;
 
volatile uint8_t sending = 0;
volatile uint16_t sent = 0;
 
volatile uint8_t data[513];
 
// ================ Functions ============== //
 
void init(void) {
    uint16_t i;
 
    // Led as output
    DDRX |= 0x0Y;
 
    // USART
    UCSRA = 0x00;   // No doubling of frequency
    UCSRB = 0xc0;   // Rx disabled, Rx irq enabled, Tx disabled, Tx irq enabled, 8bit mode
    UCSRC = 0x8e;   // Async, no parity, 2 stops, 8 bits
    UBRRL = 1;      // 250kbds
 
    // Detection timer (timer 0)
    TCCR0 = 0x03;   // 64 prescaler, increment every 4us
 
    // Set whole frame to 0
    for(i=0; i<513; i++)
        data[i] = 0x00;
}
 
void startSending(void) {
    TX = 0;         // Break
    _delay_us(100);
 
    TX = 1;         // MAB
    _delay_us(15);
 
    UCSRB |= 0x08;  // Enable TX, reset counter
    sending = 1;
    sent = 0;
 
    sendNext();     // Start sending channels
}
 
void stopSending(void) {
    UCSRB &= 0xf7;  // Disable TX
    sending = 0;
    TX = 1;
 
    _delay_us(100); // Wait between frames
 
    startSending(); // Start next frame
}
 
void sendNext(void) {
    UDR = data[sent];
 
    sent++;
 
    if(sent > FRAME_LENGTH)
        stopSending();
}
 
uint8_t startReceiving(void) {
    uint32_t t = 1500000; // 1.5s
    while(t && RX) {
        _delay_us(1);
        t--;
    }
    if(!t) return 0;
 
    RX_TIMER = 0;
    while(!RX && RX_TIMER < BREAK_LEN) _delay_us(1);
    if(RX_TIMER < BREAK_LEN) return 0; // Error, break too short
 
    while(!RX) _delay_us(1); // Wait for MAB
 
    RX_TIMER = 0;
    while(RX && RX_TIMER < MAB_LEN) _delay_us(1);
    if(RX_TIMER < MAB_LEN) return 0; // Error, break too short
 
    UCSRB |= 0x10;  // Enable RX
    receiving = 1;
 
    received = 0;   // Reset counter
 
    return 1;
}
 
void stopReceiving(void) {
    UCSRB &= 0xef;  // Disable RX
    receiving = 0;
}
 
 
// =============== Interrupts ============== //
 
SIGNAL(RX_COMPLETE) {
    uint8_t value;
    value = UDR;
 
    if(!receiving) return;
 
    if(UCSRA & 0x10) return;
    if(UCSRA & 0x08) return;
 
    received++;
 
    if(received == 1) {
        if(value != 0x00) stopReceiving(); // Should be 0x00, not a setting packet otherwise
        return; // Ignore first slot
    }
 
    if(received > 504) {
        // Do not relay more than we can handle
        stopReceiving();
        return;
    }
 
    data[received + 9] = value;
}
 
SIGNAL(TX_COMPLETE) {
    sendNext();
}
 
 
// ================== Main ================= //
 
int main(void) {
    uint16_t time_without_start = 0;
 
    cli();        // WatchDog disabled AT ALL TIMES !
    init();
    sei();
 
    BLINK;
 
    startSending(); // Start sending routine (autonomous, irq driven)
 
    while(1) {
        if(startReceiving()) {
            LED = 0;
            time_without_start = 0;
        }
        if(time_without_start > MAX_TIME_WITHOUT_START) {
            if(receiving) stopReceiving();
            BLINK;
        }
        time_without_start++;
 
        _delay_us(100);
    }
    return 0;
}

How to

Manual

dmx, microcontroller, lighting

projects/dmx_switch_box/home.txt · Last modified: 2022/06/30 21:13 by 127.0.0.1