migration atmega8515 to atmega162 in DMX

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hello I'm pretty rookie here and that's why I ask for your help
I'm trying to schedule an atmega162 with hendrik hoelscher www.hoelscher-hi.de
the original project works perfectly with atmega8515
I could not supply atmega8515 but if I obtained atmega162 compatible pin to pin
Change the USART definitions in the library as indicated by application note AVR087: Migrating between ATmega8515 and
ATmega162
The problem is that the receipt of the USART0 does not work
Specifically, I don't reception DMX signals
There are a number of issues that are not resolved
1 : clock frequency difference in AVRstudio simulator 4.13 at8515 (8.0000MHZ) and at162 (4,0000 MHZ) attached screenshot
2 : if the dieffix of UBRR0L ((F_OSC/4000)-1); is correct for at162 or should change for 16 MHZ glass
3 : if the FUSEBIT is correct in at162 according to my information of http://www.engbedded.com/fusecalc/ attached screenshot PONYPROG 2000
4 : if there is that changing the records I do not know how to do it it would be good to learn if someone teaches me how to do it would be grateful
5 : the frequency of ocilrate in "lib_dmx_in.h" line #define F_OSC (8000) must be changed

attached projects for consideration  

 

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This line in lib_dmx_in.h needs to be changed to suit the crystal frequency:

 

#define F_OSC (8000) //oscillator freq. in kHz (typical 8MHz or 16MHz)

 

 

There are some latent defects in the code - the effect will be that the timer ticks may be randomly missed. See comments:

 

int main(void)

{
cli();
init_system();
sei();
for(;;)
	{
	if (Flags &(1<<TICK))
		{
		Flags &= ~(1<<TICK);
		wdt_reset();
		if (IndCnt-- == 0)
			{
			IndCnt= IND_TIME;
			get_dips();
			indicate();
			}

		if (X.StpRate-- == 0)
			{
			eval_Xsoll();
			check_speed(&X);
			Flags |= (1<<POS_CHANGED); //*** potential atomicity problem
			}
		if (Y.StpRate-- == 0)
			{
			eval_Ysoll();
			check_speed(&Y);
			Flags |= (1<<POS_CHANGED);//*** potential atomicity problem
			}

		if (Flags &(1<<POS_CHANGED))
			{
			Flags &= ~(1<<POS_CHANGED);     //*** potential atomicity problem
			uint8_t PatBuf;
			if (PIND &(1<<PD6)) 
				{
				PatBuf= pgm_read_byte(&uStep[(X.Ist &31)]);		//get new X pattern
				}
			else PatBuf= pgm_read_byte(&buStep[(X.Ist &31)]);
			OCR1A= pgm_read_word(&uAngle[(X.Ist &0b111)]);
			X.TopPat = (PatBuf>>4);
			PatBuf= (PatBuf &0b00001111);
			uint8_t Ytmp;
			if (PIND &(1<<PD6)) 
				{
				Ytmp= pgm_read_byte(&uStep[(Y.Ist &31)]);		//get new Y pattern
				}
			else Ytmp= pgm_read_byte(&buStep[(Y.Ist &31)]);
			OCR1B= pgm_read_word(&uAngle[(Y.Ist &0b111)]);
			Y.TopPat = (Ytmp &0b11110000);
			PatBuf |= (Ytmp<<4);
			BasePat= PatBuf;
			}
		}
	};
}

 

 

The fix:

 

/**** A P P L I C A T I O N   N O T E   ************************************
*
* Title		: DMX512 2 axis microstep controller
* Version		: v1.1
* Last updated	: 03.04.08
* Target		: Transceiver Rev.3.01 [ATmega8515]
* Clock			: 8MHz
*
* written by hendrik hoelscher, www.hoelscher-hi.de
***************************************************************************
 This program is free software; you can redistribute it and/or 
 modify it under the terms of the GNU General Public License 
 as published by the Free Software Foundation; either version2 of 
 the License, or (at your option) any later version. 

 This program is distributed in the hope that it will be useful, 
 but WITHOUT ANY WARRANTY; without even the implied warranty of 
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 General Public License for more details. 

 If you have no copy of the GNU General Public License, write to the 
 Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 

 For other license models, please contact the author.

;***************************************************************************/

#include "lib_indicator.h"
#include "lib_dmx_in.h"
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include <util/delay.h>


		
uint16_t  Accel;
uint8_t   Flags;
volatile uint8_t tickFlag;
uint16_t  IndCnt= 1000;
volatile uint8_t   BasePat;



		struct axis{				//all private data for X and Y axes
		   uint16_t   Ist;			//current position
		   uint16_t	  Soll;			//destination pos
		   uint16_t   Max;			//max position
           uint8_t	  State;		//status flags
		   int8_t	  Speed;      	//current speed (raw)
		   uint16_t   StpRate;
		   uint8_t 	  TopPat;		//PWM pattern
		   };
		   
		struct axis X;
		struct axis Y;


enum {TICK, POS_CHANGED};
enum {POS};

#define OFFSET		(4)
#define IND_TIME	(2200)

#define X_MAX_H		(1)				//EEPROM usage
#define X_MAX_L		(2)
#define Y_MAX_H		(3)
#define Y_MAX_L		(4)
#define ACC_H		(5)
#define ACC_L		(6)


const uint8_t bStep[] PROGMEM =	{								//halfsteps (DCBA DCBA)
									0b00010001,
									0b01010101,
									0b01000100,
									0b01100110,
									0b00100010,
									0b10101010,
									0b10001000,
									0b10011001,
									0b00010001
								};
const uint8_t buStep[] PROGMEM =	{							//1/8 steps
								    0b00010001,

									0b01010001,
									0b01010001,
									0b01010001,

									0b01010101,

									0b01010100,
									0b01010100,
									0b01010100,

									0b01000100,

									0b01100100,
									0b01100100,
									0b01100100,

									0b01100110,

									0b01100010,
									0b01100010,
									0b01100010,

									0b00100010,

									0b10100010,
									0b10100010,
									0b10100010,

									0b10101010,

									0b10101000,
									0b10101000,
									0b10101000,

									0b10001000,

									0b10011000,
									0b10011000,
									0b10011000,

									0b10011001,

									0b10010001,
									0b10010001,
									0b10010001,

									0b00010001
								};	



const uint8_t Step[] PROGMEM =	{								//halfsteps
									0b00010001,
									0b00110011,
									0b00100010,
									0b01100110,
									0b01000100,
									0b11001100,
									0b10001000,
									0b10011001,
									0b00010001
								};
const uint8_t uStep[] PROGMEM =	{								//1/8 steps
									0b00010001,

									0b00110001,
									0b00110001,
									0b00110001,

									0b00110011,

									0b00110010,
									0b00110010,
									0b00110010,

									0b00100010,

									0b01100010,
									0b01100010,
									0b01100010,

									0b01100110,

									0b01100100,
									0b01100100,
									0b01100100,

									0b01000100,

									0b11000100,
									0b11000100,
									0b11000100,

									0b11001100,

									0b11001000,
									0b11001000,
									0b11001000,

									0b10001000, 

									0b10011000,
									0b10011000,
									0b10011000,

									0b10011001,

									0b10010001,
									0b10010001,
									0b10010001,

									0b00010001
									};

const uint16_t uAngle[] PROGMEM = {
0xF0, 176, 90, 41, 0xF0, 41, 90, 176
};



const uint16_t Ramp[] PROGMEM = {								//acceleration, deceleration (step durations)
27145, 20829, 17560, 15471, 13987, 12862, 11972, 11244, 10635, 10115, 9665,  9270,  8920,  8606, 
8324,  8068,  7834,  7619,  7421,  7238,  7067,  6908,  6760,  6620,  6489,  6366,  6249,  6138, 
6033,  5933,  5839,  5748,  5662,  5579,  5500,  5424,  5351,  5281,  5214,  5149,  5087,  5026, 
4968,  4912,  4858,  4805,  4754,  4705,  4657,  4611,  4566,  4522	
};




// *************** Stepper Homing ****************
void home_stepper(void)
{
//postion reset (homing)
uint8_t tmp, tmpA= 0, tmpB= 0;
X.Ist= (X.Max>>1) +20 +OFFSET;
Y.Ist= (Y.Max>>1) +20 +OFFSET;
uint16_t delay;
while ((X.Ist != OFFSET) || (Y.Ist != OFFSET))
   {
	if (X.Ist > OFFSET)
		{
		if (PIND &(1<<PD4))
			{
			if (PIND &(1<<PD6)) tmpA= pgm_read_byte(&Step[(--X.Ist &7)]); //move through full range (open loop)
			else		        tmpA= pgm_read_byte(&bStep[(--X.Ist &7)]);
			tmpA &= 0b00001111;
			}
		else X.Ist= OFFSET;											//Anschlag detected (closed loop reference)
		}
	if (Y.Ist > OFFSET)
		{
		if (PIND &(1<<PD5))
			{
			if (PIND &(1<<PD6)) tmpB= pgm_read_byte(&Step[(--Y.Ist &7)]);
			else		        tmpB= pgm_read_byte(&bStep[(--Y.Ist &7)]);
			tmpB &= 0b11110000;
			}
		else Y.Ist= OFFSET;
		}
	tmp= tmpA;
	tmp |= tmpB;
	PORTA= tmp;
	wdt_reset();
	delay= Accel>>1;
	while (delay != 0)
		{
		_delay_us(35);
		delay--;
		} 
	}

}




// *************** Initialization ****************
void init_system(void)
{
wdt_reset();
wdt_enable(WDTO_500MS);											//enable watchdog (Timeout= 0.5s)
wdt_reset();

DDRA=  0xFF;													//low outputs
PORTA= 0;

DDRD=  0b10000110;												//DMX, spare, LED1
PORTD= 0b01111010;

TCCR1A = (1<<WGM10);
TCCR1B = (1<<CS10)|(1<<WGM12);									//set T1 @clock freq, 8bit fast PWM
TIMSK |= (1<<TOIE1)|(1<<OCIE1A)|(1<<OCIE1B);					//enable compare and overflow interrupts (u-step, system)


if (eeprom_read_byte(0) == 1)
	{
	X.Max= (uint16_t)(eeprom_read_byte(X_MAX_H)<<8) +(uint16_t)eeprom_read_byte(X_MAX_L);
	Y.Max= (uint16_t)(eeprom_read_byte(Y_MAX_H)<<8) +(uint16_t)eeprom_read_byte(Y_MAX_L);
	Accel= (uint16_t)(eeprom_read_byte(ACC_H)<<8)   +(uint16_t)eeprom_read_byte(ACC_L);
	}
else
	{
	X.Max= 1600;
	Y.Max= 1600;
	Accel= 256;
	}

home_stepper();
init_ind();
init_DMX_RX();
get_dips();
}




// *************** Stepper speed control ****************
void check_speed(struct axis* Stp)
{
if (abs(Stp->Soll -Stp->Ist) <= abs(Stp->Speed))				//decel speed short before target position
	{
	if      (Stp->Speed < 0) Stp->Speed++;
	else if (Stp->Speed > 0) Stp->Speed--; 				
	}

else if (Stp->Ist < Stp->Soll)									//shall move in positive direction
	{
	if (Stp->Speed < 50) Stp->Speed++; 							//accel speed
	}

else if (Stp->Ist > Stp->Soll)									//shall move in negative direction
	{
	if (Stp->Speed > -50) Stp->Speed--; 						//accel speed
	}

if      (Stp->Speed > 0) Stp->Ist++;
else if (Stp->Speed < 0) Stp->Ist--;

uint32_t tmp= (uint32_t)pgm_read_word(&Ramp[abs(Stp->Speed)]);
Stp->StpRate= (tmp * Accel)>>16;
}



// *************** Soll Positions ****************
void eval_Xsoll(void)
{
uint32_t tmp= ((uint32_t)DmxRxField[0]<<8) +(uint32_t)DmxRxField[1];
tmp= OFFSET +((tmp * X.Max)>>16);
if (tmp != X.Soll)
	{
	X.Soll= tmp;
	IndFlags |= (1<<DATA_REFRESHED);
	}
}

void eval_Ysoll(void)
{
uint32_t tmp= ((uint32_t)DmxRxField[2]<<8) +(uint32_t)DmxRxField[3];
tmp= OFFSET +((tmp * Y.Max)>>16);
if (tmp != Y.Soll)
	{
	Y.Soll= tmp;
	IndFlags |= (1<<DATA_REFRESHED);
	}
}







int main(void)

{
cli();
init_system();
tickFlag = 0;
sei();
for(;;)
	{
	if (tickFlag)
		{
		tickFlag = 0;
		wdt_reset();
		if (IndCnt-- == 0)
			{
			IndCnt= IND_TIME;
			get_dips();
			indicate();
			}

		if (X.StpRate-- == 0)
			{
			eval_Xsoll();
			check_speed(&X);
			Flags |= (1<<POS_CHANGED);
			}
		if (Y.StpRate-- == 0)
			{
			eval_Ysoll();
			check_speed(&Y);
			Flags |= (1<<POS_CHANGED);
			}

		if (Flags &(1<<POS_CHANGED))
			{
			Flags &= ~(1<<POS_CHANGED);
			uint8_t PatBuf;
			if (PIND &(1<<PD6)) 
				{
				PatBuf= pgm_read_byte(&uStep[(X.Ist &31)]);		//get new X pattern
				}
			else PatBuf= pgm_read_byte(&buStep[(X.Ist &31)]);
			OCR1A= pgm_read_word(&uAngle[(X.Ist &0b111)]);
			X.TopPat = (PatBuf>>4);
			PatBuf= (PatBuf &0b00001111);
			uint8_t Ytmp;
			if (PIND &(1<<PD6)) 
				{
				Ytmp= pgm_read_byte(&uStep[(Y.Ist &31)]);		//get new Y pattern
				}
			else Ytmp= pgm_read_byte(&buStep[(Y.Ist &31)]);
			OCR1B= pgm_read_word(&uAngle[(Y.Ist &0b111)]);
			Y.TopPat = (Ytmp &0b11110000);
			PatBuf |= (Ytmp<<4);
			BasePat= PatBuf;
			}
		}
	};
}



// *************** ISRs ****************
ISR (TIMER1_OVF_vect)											
{														//half step
tickFlag = 1;										//tick system
PORTA= BasePat;
}


ISR (TIMER1_COMPA_vect)									//X-axis �-Stepping
{
uint8_t buf;
buf  = PORTA;
buf &= 0b11110000;
buf |= X.TopPat;
PORTA= buf;
}


ISR (TIMER1_COMPB_vect)									//Y-Axis �-Stepping
{
uint8_t buf;
buf  = PORTA;
buf &= 0b00001111;
buf |= Y.TopPat;
PORTA= buf;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman thank you very much for your help and collaboration
My problem is not in the loop function execution
I have not receipt of the USART0 and can not find the reason
Deputy project on TEST

 

TEST MAIN .C

#include "lib_dmx_in.h"

int main(void)
{
cli();
DDRD |= (1<<PD7);                    //red LED pin is output
DDRE |= (1<<PE0);                    //green LED pin is output

init_DMX_RX();
// DmxAddress= 1;
sei();
for(;;)
    {
    get_dips();                        //get start address
    if (DmxRxField[0] >= 127)        //enable LED if 1st DMX val is >127
        {
        PORTD &= ~(1<<PD7);            //LED ON
        }
    else
        {
        PORTD |= (1<<PD7);            //LED OFF
         }
    if (DmxRxField[1] >= 127)        //enable LED if 1st DMX val is >127
        {
        PORTE &= ~(1<<PE0);            //LED ON
        }
    else
        {
        PORTE |= (1<<PE0);            //LED OFF

        }
    }
 }

 

DMX-in
 

/**** A P P L I C A T I O N   N O T E   ************************************
*
* Title            : DMX512 reception library
* Version        : v1.3
* Last updated    : 13.04.09
* Target        : Transceiver Rev.3.01 [ATmega8515]
* Clock            : 8MHz, 16MHz
*
* written by hendrik hoelscher, www.hoelscher-hi.de
***************************************************************************
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version2 of
 the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 General Public License for more details.

 If you have no copy of the GNU General Public License, write to the
 Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 For other license models, please contact the author.

;***************************************************************************/

#include "lib_dmx_in.h"

// ********************* local definitions *********************

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

volatile uint8_t      gDmxState;

// *************** DMX Reception Initialisation ****************
void init_DMX_RX(void)
{
#ifdef USE_DIP
DDRC   = 0;                                        //set up DIPs
PORTC  = 0xFF;
DDRE  &= ~((1<<PE2)|(1<<PE1));
PORTE |=   (1<<PE2)|(1<<PE1);
#endif

DDRD  |= (1<<2);
PORTD &= ~(1<<2);                                
UBRR0H  = 0;                                        //enable reception
UBRR0L  = ((F_OSC/4000)-1);                        //250kbaud, 8N2
UCSR0C  = (1<<URSEL0)|(3<<UCSZ00)|(1<<USBS0);
UCSR0B  = (1<<RXEN0)|(1<<RXCIE0

 

 

 

 

);
gDmxState= IDLE;
}

 

// ************* get DMX start address **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp= (0xFF-PINC);                        //invert DIP state
if (!(PINE &(1<<2)))
    {
    Temp += 256;                                //9th bit
    }
if (Temp != 0)
    {
    DmxAddress= Temp;
    if (!(UCSR0B &(1<<RXCIE0)))                    //if receiver was disabled -> enable and wait for break
        {
        gDmxState= IDLE;
        UCSR0B |= (1<<RXCIE0);
        }
    }
else
    {
    UCSR0B &= ~(1<<RXCIE0);                        //disable Receiver if start address = 0
    uint8_t i;
    for (i=0; i<sizeof(DmxRxField); i++)
        {
        DmxRxField[i]= 0;
        }
    }
#endif
}

 

// *************** DMX Reception ISR ****************
ISR (USART0_RXC_vect)
{
static  uint16_t DmxCount;
        uint8_t  USARTstate= UCSR0A;                //get state before data!
        uint8_t  DmxByte   = UDRE0;                //get data
        uint8_t  DmxState  = gDmxState;            //just load once from SRAM to increase speed
 
if (USARTstate &(1<<FE0))                        //check for break
    {
    UCSR0A &= ~(1<<FE0);                            //reset flag (necessary for simulation in AVR Studio)
    DmxCount =  DmxAddress;                        //reset channel counter (count channels before start address)
    gDmxState= BREAK;
    }

else if (DmxState == BREAK)
    {
    if (DmxByte == 0) gDmxState= STARTB;        //normal start code detected
    else              gDmxState= IDLE;
    }
    
else if (DmxState == STARTB)
    {
    if (--DmxCount == 0)                        //start address reached?
        {
        DmxCount= 1;                            //set up counter for required channels
        DmxRxField[0]= DmxByte;                    //get 1st DMX channel of device
        gDmxState= STARTADR;
        }
    }

else if (DmxState == STARTADR)
    {
    DmxRxField[DmxCount++]= DmxByte;            //get channel
    if (DmxCount >= sizeof(DmxRxField))         //all ch received?
        {
        gDmxState= IDLE;                        //wait for next break
        }
    }                            
}

 

 

dmx_in.h

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

#define  USE_DIP
#define  F_OSC            (16000)                  //oscillator freq. in kHz (typical 8MHz or 16MHz)

volatile uint8_t     DmxRxField[8];         //array of DMX vals (raw)
volatile uint16_t     DmxAddress;            //start address

extern void    init_DMX_RX(void);
extern void    get_dips(void);

 

but I still have the 4.0000mhz running in the simulator

and making the changes indicated in the glass

 

Attachment(s): 

Last Edited: Mon. Nov 25, 2019 - 05:25 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

locodelafonola wrote:
My problem is not in the loop function execution
Yes, but it is a problem you don't know you have.

 

First you need to verify that your mega162 is really running at 16MHz. Write simple code using delays to flash a led. If the led flashes at the programmed speed, then the speed is correct.

 

do you have access to an oscilloscope?

 

https://www.youtube.com/watch?v=...

or maybe you can purchase this locally. They are usually around $10USD

 

 

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't think that the fuse calculate program is working.  Do you have a crystal-driven clock on the Mega162?  If not then, download the ATMega162 datasheet and set the fuses for internal RC at 8MHz ( make sure that the Divide_System_Clock_8 fuse is off).

 

The USART formula is UBBRL = ( Fosc/ (16 * baudrate) )  - 1;   with Fosc==8000000 and baudrate==250000.   You may have to use the double speed feature of the mega162  USART to get DMX baud rates of 250000 bits/second, but UBBRL==1 should work for an 8MHz Fosc.    The instruction : UBBRL = Fosc/4000-1  is a "magic number" instruction and probably only works on the Mega8515 system. 

 

The Mega162 has two USARTS.  Make sure that the system is using the right one.

 

Do you really need a 40-pin CPU to run a DMX controller (which is basically an RS485 serial bus system running at 250Kbaud)?  If most of the other pins are unused, then you could use a 16MHz Arduino Nano board with Open Source DMX libraries. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello and thank you very much KARTMAN and SIMONETTA in its time and knowledge spilled in me
I have achieved that the bookstore works in atmega162 with crystal 8MHZ
The problem was in my bad interpretation of the sheet of information
Specifically in the line

 

 

uint8_t  DmxByte   = UDRE0;                //get data

 

where the correct thing is

 

 uint8_t  DmxByte   = UDR0;                //get data

 

And magically it began to work quite
Here a video working

 

https://youtu.be/w4zPm1umnVY

 

 

Although the problem is solved for me
I would like that they were bringing me its knowledge to learn
I have several questions that the solution of my doubts did not achieve
Beginning for the compiler AVR studio 4.13 and specifically in the part of the pretender
And it is the question of the reason in atmega8515 it simulates in 8mhz as it appears in this screen apprehension

 

My consultation is that I must do or form so that the pretender works correctly in atmega162 8MHZ
And not in 4MHZ since it is appreciated in this screen apprehensio

 

It would be very grateful if they were helping me to solve this question first and then to continue with the others

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0