CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

[solved] dmx512 receiver?
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Ttelmah



Joined: 11 Mar 2010
Posts: 20061

View user's profile Send private message

PostPosted: Sun Mar 06, 2016 11:13 am     Reply with quote

Comments inline:
Code:

#use rs232(uart2, baud=9600, stream=STD)

#use rs232(UART1, BAUD=250000,BITS=9,PARITY=N,STOP=1,ERRORS,stream=DMX, LONG_DATA)
//You are ignoring what you were told. The UART cannot generate 2 stops
//by selecting 2 stops you are forcing a software UART to be used...

int16 break_time;
int8 dmx_in[128]; //You are only using 8bit data
char dmx_index=0;
//You don't show a declaration for int_count
int16 int_count=500;

void main(void)
{
    set_tris_d(0b01111111);

    setup_timer_2(T2_DIV_BY_4,249,10);
    enable_interrupts(INT_TIMER1);
    enable_interrupts(INT_RDA);    //Again answered at the start of the
//thread. UART1 gives INT_RDA. UART2 INT_RDA2
    enable_interrupts(GLOBAL);
    while(TRUE)
    {
        fprintf(STD, "value: %d\r\n", dmx_in[0]);
        fprintf(STD, "value: %d\r\n", dmx_in[1]);
        fprintf(STD, "value: %d\r\n", dmx_in[2]);
        fprintf(STD, "value: %d\r\n", dmx_in[3]);
        delay_ms(1000);

    }
}

#INT_RDA
void dmx() {
    // Is this a receiver interrupt on the DMX stream? It does not trigger...
    //Because you are not using the UART.....
    output_toggle(PIN_E1);
    dmx_in[dmx_index++] = (int8)fgetc(DMX);
//Just store the low 8bits of the value
    if (index==128)
       index=127; //ensure this cannot overflow.
}

#INT_TIMER2
void timer2_isr()
{
    // Timer interrupt every 1 mSec
    if(--int_count==0) {           // this program.
        output_toggle(PIN_C1);
        int_count = 500;
    }
    break_time++;
    if (break_time > 15)
        dmx_index = 0;
}
JackB



Joined: 04 Mar 2016
Posts: 32
Location: Netherlands

View user's profile Send private message

PostPosted: Sun Mar 06, 2016 12:28 pm     Reply with quote

Hi Ttelmah,

Thank you very much for helping!
The once missing declaration was sitting in main.h, I moved it for clarity now.
One I enable INT_RDA, the timer interrupt gets slow and does no longer trigger per ms.
but about every 2 ms. Also when I disconnect the DMX signal.
My output is not printed to the serial port to the PC as well if that interrupt is enabled.
In my code I use multiple files for different parts, they all work fine, like adc, pwm, lm75, etc.

I get a compiler error:
A numeric expression must appear here
For this line within INT_RDA:
Code:
    dmx_in[dmx_index++] = (int8)fgetc(DMX);

If I comment this out, the code compiles.

I will now list the entire main.c and project.h, so maybe somebody can see what is wrong.
Both with the complier error as well as with slowing down and no longer printing output once this line is uncommented:
Code:
 enable_interrupts(INT_RDA);     // UART1 gives INT_RDA

If the above line is commented out the rest of the code works fine.

project.h
Code:

#ifndef PROJECT_H
#define   PROJECT_H

#include <18F67K90.h>

#fuses MCLR,HSH,NOPLLEN

#device ADC=12

#use delay(crystal=20mhz)

#use rs232(UART1, BAUD=250000,BITS=9,PARITY=N,STOP=1,ERRORS,stream=DMX, LONG_DATA)

#use rs232(uart2, baud=9600, stream=STD)

#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3)

enum errors { err_range, err_too_far, err_too_many };

#endif   /* PROJECT_H */


main.c
Code:

#include "project.h"
#include "main.h"
#include "leds.h"
#include "switches.h"
#include "lm75.h"
#include "mcp7940n.h"
#include "pwm.h"
#include "adc.h"
#include "eeprom.h"
#include "dmx_receive.h"

int16 int_count;
int8 dmx_in[128];
char dmx_index;
int16 dmx_value;
int16 break_time;
int16 msecs;

void main()
{
    fprintf(STD, "\r\nHello LED driver!\r\n");
 
    dmx_index = 0;
    msecs = 0;
//    delay_cycles(4);

    init_switches();
    init_leds();

    int_count = 500;

    setup_timer_2(T2_DIV_BY_4, 249, 10);

    enable_interrupts(INT_TIMER2);

    enable_interrupts(INT_RDA);     // UART1 gives INT_RDA
//    enable_interrupts(INT_RDA2);    // UART2 gives INT_RDA2
   
    enable_interrupts(GLOBAL);

   
    init_pwm();     // 1.25kHz
    set_pwm1(50);   // 20%
    set_pwm2(100);  // 40%
    set_pwm3(150);  // 60%
    set_pwm4(200);  // 80%
    set_pwm5(250);  // 100%
   
    init_adc();
   
    unsigned long count = eeprom_read_16(0);

   
    while(1)
    {
        restart_wdt();

        float temperature = read_lm75(7);
        float ol1 = read_overload1_amps();
        float ol2 = read_overload2_amps();
        float ol3 = read_overload3_amps();
        float ol4 = read_overload4_amps();
        float ol5 = read_overload5_amps();
        if (temperature > 70)
        {
            set_leds(6, 1);
        } else {
            set_leds(6, 0);
            if (ol1 > 10) set_leds(1, 1);
            if (ol2 > 10) set_leds(2, 1);
            if (ol3 > 10) set_leds(3, 1);
            if (ol4 > 10) set_leds(4, 1);
            if (ol5 > 10) set_leds(5, 1);
        }

        if (msecs == 1000)
        {
            msecs = 0;
            fprintf(STD, "current: %4.1fA, %4.1fA, %4.1fA, %4.1fA, %4.1fA", ol1, ol2, ol3, ol4, ol5);

            fprintf(STD, ", value: %d %d %d %d %d", dmx_in[0], dmx_in[1], dmx_in[2], dmx_in[3], dmx_in[4]);

            float pwm1 = get_pwm1_float();
            float pwm2 = get_pwm2_float();
            float pwm3 = get_pwm3_float();
            float pwm4 = get_pwm4_float();
            float pwm5 = get_pwm5_float();
            fprintf(STD, ", pwm: %3.0f, %3.0f, %3.0f, %3.0f, %3.0f", pwm1, pwm2, pwm3, pwm4, pwm5);
       
            fprintf(STD, ", temp: %3.1f °C ", temperature);

            int options = read_option_switches();
            long int dmx = read_dmx_switches();
            char options[6];
            fprintf(STD, ", options: %d, dmx: %ld", options, dmx);

            fprintf(STD, ", count: %06ld", count++);

            fprintf(STD, "\r\n");

            eeprom_write_16(0, count);

        }
    }
}

#INT_RDA
void dmx() {
    // Is this receiver interrupt on the DMX stream? Does not trigger?
//    dmx_in[dmx_index++] = (int8)fgetc(DMX);
//    if (dmx_index==128)
//       dmx_index=127; //ensure this cannot overflow.
    output_toggle(PIN_D7);
}

#INT_TIMER2
void timer2_isr()
{
    // Timer interrupt every 1 mSec
    if(--int_count==0) {           // this program.
        output_toggle(PIN_C1);
        int_count = 500;
    }
    break_time++;
    msecs++;
    if (break_time > 15)
        dmx_index = 0;
       
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 06, 2016 1:36 pm     Reply with quote

Quote:
I get a compiler error:
A numeric expression must appear here
For this line within INT_RDA:
Code:
dmx_in[dmx_index++] = (int8)fgetc(DMX);

That's because you named the isr with the same name as the stream.
Apparently the compiler doesn't like that.
Quote:

#use rs232(UART1, BAUD=250000,BITS=9,PARITY=N,STOP=1,ERRORS,stream=DMX, LONG_DATA)

#INT_RDA
void dmx() {
// Is this receiver interrupt on the DMX stream? Does not trigger?
// dmx_in[dmx_index++] = (int8)fgetc(DMX);
// if (dmx_index==128)
// dmx_index=127; //ensure this cannot overflow.
output_toggle(PIN_D7);
}

Rename it to dmx_isr() or something like that. I always do this.

Alternatively, using #case also fixes the problem.
Code:
#include <18F67K90.h>
#case

But renaming the routine as dmx_isr() is the best way.


Quote:
Both with the complier error as well as with slowing down and no longer printing output once this line is uncommented:
Code:
enable_interrupts(INT_RDA); // UART1 gives INT_RDA

If you comment out the fgetc() line in the isr, the program will fail.
You must read (get) the character in the isr.
Ttelmah



Joined: 11 Mar 2010
Posts: 20061

View user's profile Send private message

PostPosted: Sun Mar 06, 2016 1:47 pm     Reply with quote

But also do keep the test on index size for the array, which you show removed.
Problem is that if (shouldn't happen, but 'if' often does), data keeps arriving without the break, you will start writing beyond the end of the array. A sure way of making the code go haywire.
JackB



Joined: 04 Mar 2016
Posts: 32
Location: Netherlands

View user's profile Send private message

PostPosted: Sun Mar 06, 2016 2:18 pm     Reply with quote

Hi thank you both!
Renaming to dmx_isr makes sense and that worked!
I also include the code to avoid crossing the buffer boundary.
But I had to comment it out because of the compiler error, which got solved now.
I need indeed to read the value in the isr to clear the interrupt. (I guess)
Temporary (compiler error) not doing that made the controller behave odd. (slow)

The heartbeat LED now blinks at 1Hz rate, which is good!
Printed code stops after a few seconds, and then goes on.
The data read from the dmx signal is is read as 0 0 0 0 0 or 0 0 0 78 0, where 78 is correct!

We are getting close, I guess!
Ttelmah



Joined: 11 Mar 2010
Posts: 20061

View user's profile Send private message

PostPosted: Sun Mar 06, 2016 3:03 pm     Reply with quote

There is one critical thing missing.

In the Microchip code, dmx_break_time is set to zero whenever a byte is received. This way it'll only get to 15, when there is a gap in the characters. Your CCS code does not do this.
JackB



Joined: 04 Mar 2016
Posts: 32
Location: Netherlands

View user's profile Send private message

PostPosted: Mon Mar 07, 2016 8:04 am     Reply with quote

Thank you all! It is working very well!
How it was done in the end...

At Ttelmah, thank you very much for checking with me.
The break_time should only get to 15 during the break in the dmx signal.
Then the index is set to 0.
This is a way to know we are starting over the same sequence of received bytes.
First a value for dmx address 0, then for 1, and so up.

But do I need to clear framing errors and overrrun errors? (like I do with XC8)
How do I check for framing errors and clear them?

In some include file:
Code:

#use rs232(UART1, BAUD=250000,BITS=9,PARITY=N,STOP=1,ERRORS,stream=DMX, LONG_DATA)


(Part of) main.c
Code:

int16 int_count;
int8 dmx_in[128];
char dmx_index;
int16 dmx_value;
int16 dmx_break_time;
int16 msecs;
int8 dmx_signal_detected;

void main()
{
    setup_timer_2(T2_DIV_BY_4, 249, 10);
    enable_interrupts(INT_TIMER2);
    enable_interrupts(INT_RDA);     // UART1 gives INT_RDA
//    enable_interrupts(INT_RDA2);    // UART2 gives INT_RDA2
    enable_interrupts(GLOBAL);
    msecs = 0;
    dmx_break_time = 0;
    dmx_signal_detected = 0;

    while(1)
    {
        set_pwm1(dmx_in[0+dmx_address]);
        set_pwm2(dmx_in[1+dmx_address]);
        set_pwm3(dmx_in[2+dmx_address]);
        set_pwm4(dmx_in[3+dmx_address]);
        set_pwm5(dmx_in[4+dmx_address]);
        if (msecs >= 1000)
        {
            // Do this every second
            msecs = 0;
            restart_wdt();
            dmx_address = read_dmx_switches();
        }
    }
}

#INT_RDA
void dmx_isr() {
    // Is this receiver interrupt on the DMX stream? Does not trigger?
    dmx_in[dmx_index++] = (int8)fgetc(DMX);
    if (dmx_index==128)
       dmx_index=127;           // Ensure this cannot overflow.
    if (dmx_break_time > 15) {        // MARK time after Slot > 15mS, reset index
        dmx_index = 0;
        dmx_signal_detected = 1;    // Flag indicates presence of DMX signal
    }
    dmx_break_time = 0;             // Character received: reset break time
}

#INT_TIMER2
void timer2_isr()
{
    // Timer interrupt every 1 mSec
    if(--int_count==0) {           // this program.
        output_toggle(PIN_C1);      // Heartbeat LED
        int_count = 500;
    }
    if (dmx_break_time < 1000)
        dmx_break_time++;       // Increase measured break time by 1 mSec
    if (dmx_break_time > 100)
        dmx_signal_detected = 0;    // Flag indicates presence of DMX signal
    msecs++;       
}


Last edited by JackB on Mon Mar 07, 2016 1:24 pm; edited 16 times in total
Ttelmah



Joined: 11 Mar 2010
Posts: 20061

View user's profile Send private message

PostPosted: Mon Mar 07, 2016 8:16 am     Reply with quote

Good. Smile

Mark the thread as 'solved' (only you can do this), then somebody else wanting stuff about DMX in the future can know there is a solution.

Best Wishes
JackB



Joined: 04 Mar 2016
Posts: 32
Location: Netherlands

View user's profile Send private message

PostPosted: Mon Mar 07, 2016 8:47 am     Reply with quote

The only open question is this:
Do I need to clear framing errors and overrrun errors? (like I do with XC8)
How do I check for framing errors and clear them?
Ttelmah



Joined: 11 Mar 2010
Posts: 20061

View user's profile Send private message

PostPosted: Mon Mar 07, 2016 9:06 am     Reply with quote

If you have 'ERRORS' in the #USE RS232 (you do), the compiler clears these automatically when the UART is read (actually copies them into a variable called 'RS232_ERRORS', so you can test them if needed). Without 'ERRORS', you have to clear them yourself.
temtronic



Joined: 01 Jul 2010
Posts: 9632
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Mar 07, 2016 9:49 am     Reply with quote

I've been following this 'thread' and I think we've another convert !!

It looks like nice, clean, easy to read code.

Well done.

Jay
JackB



Joined: 04 Mar 2016
Posts: 32
Location: Netherlands

View user's profile Send private message

PostPosted: Mon Mar 07, 2016 10:45 am     Reply with quote

Thank you all for your great support!
I'm new to this and learning a lot from you, guys! Very Happy

How do I mark the thread as 'solved' ?
temtronic



Joined: 01 Jul 2010
Posts: 9632
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Mar 07, 2016 12:31 pm     Reply with quote

easy.. just open the thread up, goto first post, click 'edit' then add [solved] in the subject line.

Jay
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group