please help with encoder on xmega

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

Hi!

I try read encoder connected to xplain board.
Encoder connected to pins 0 and 1 of PORTD.
Inputs of PORTD.0 and PORTD.1 are oututs to leds connected to PORTE. Leds are flashes when encoder rotating.
I output timer counter values into LCD.
Probles is that counter values such as if they are random :(

I use codevision compiler.

.................

// Event System initialization
void event_system_init(void)
{
// Event System Channel 0 source: Port D, Pin0
EVSYS.CH0MUX=EVSYS_CHMUX_PORTD_PIN0_gc;
// Event System Channel 1 source: None
EVSYS.CH1MUX=EVSYS_CHMUX_OFF_gc;


...............


// PORTD initialization
// OUT register
PORTD.OUT=0x00;
// Bit0:7: Input
PORTD.DIR=0x00;
// Bit0 Output/Pull configuration: Totempole/No
// Bit0 Input/Sense configuration: Sense low level
// Bit0 inverted: Off
// Bit0 slew rate limitation: Off
PORTD.PIN0CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_LEVEL_gc;
// Bit1 Output/Pull configuration: Totempole/No
// Bit1 Input/Sense configuration: Sense low level
// Bit1 inverted: Off
// Bit1 slew rate limitation: Off
PORTD.PIN1CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_LEVEL_gc;
// Bit2 Output/Pull configuration: Totempole/No
// Bit2 Input/Sense configuration: Sense both edges
// Bit2 inverted: Off
// Bit2 slew rate limitation: Off

.......................

// Disable and reset the timer/counter just to be sure
tc0_disable(&TCC0);
// Clock source: Peripheral Clock/1
TCC0.CTRLA=(TCC0.CTRLA & (~TC0_CLKSEL_gm)) | TC_CLKSEL_DIV64_gc;
// Mode: Normal Operation, Overflow Int./Event on TOP
// Compare/Capture on channel A:D: Off
TCC0.CTRLB=(TCC0.CTRLB & (~(TC0_CCAEN_bm | TC0_CCBEN_bm | TC0_CCCEN_bm | TC0_CCDEN_bm | TC0_WGMODE_gm))) |
	TC_WGMODE_NORMAL_gc;

// Capture event source: Event Channel 0
// Capture event action: Quadrature Decode
TCC0.CTRLD=(TCC0.CTRLD & (~(TC0_EVACT_gm | TC0_EVSEL_gm))) |
	TC_EVACT_QDEC_gc | TC_EVSEL_CH0_gc;

// Overflow interrupt: Disabled
// Error interrupt: Disabled
TCC0.INTCTRLA=(TCC0.INTCTRLA & (~(TC0_ERRINTLVL_gm | TC0_OVFINTLVL_gm))) |
	TC_ERRINTLVL_OFF_gc | TC_OVFINTLVL_OFF_gc;

// Compare/Capture channel A:D interrupt: Disabled
TCC0.INTCTRLB=(TCC0.INTCTRLB & (~(TC0_CCDINTLVL_gm | TC0_CCCINTLVL_gm | TC0_CCBINTLVL_gm | TC0_CCAINTLVL_gm))) |
	TC_CCDINTLVL_OFF_gc | TC_CCCINTLVL_OFF_gc | TC_CCBINTLVL_OFF_gc | TC_CCAINTLVL_OFF_gc;

// High resolution extension: Off
HIRESC.CTRL&= ~HIRES_HREN0_bm;

// Advanced Waveform Extension initialization
// Optimize for speed
#pragma optsize- 
// Disable locking the AWEX configuration registers just to be sure
n=MCU.AWEXLOCK & (~MCU_AWEXCLOCK_bm);
CCP=CCP_IOREG_gc;
MCU.AWEXLOCK=n;
// Restore optimization for size if needed
#pragma optsize_default

// Pattern generation: Off
// Dead time insertion: Off
AWEXC.CTRL&= ~(AWEX_PGM_bm | AWEX_CWCM_bm | AWEX_DTICCDEN_bm | AWEX_DTICCCEN_bm | AWEX_DTICCBEN_bm | AWEX_DTICCAEN_bm);

// Fault protection initialization
// Fault detection on OCD Break detection: On
// Fault detection restart mode: Latched Mode
// Fault detection action: None (Fault protection disabled)
AWEXC.FDCTRL=(AWEXC.FDCTRL & (~(AWEX_FDDBD_bm | AWEX_FDMODE_bm | AWEX_FDACT_gm))) |
	AWEX_FDACT_NONE_gc;
// Fault detect events: 
// Event channel 0:7: Off
AWEXC.FDEVMASK=0b00000000;
// Make sure the fault detect flag is cleared
AWEXC.STATUS|=AWEXC.STATUS & AWEX_FDF_bm;

// Clear the interrupt flags
TCC0.INTFLAGS=TCC0.INTFLAGS;
// Set counter register
TCC0.CNT=0x0000;
// Set period register
TCC0.PER=3999;
// Set channel A:D Compare/Capture register
TCC0.CCA=0x0000;
TCC0.CCB=0x0000;
TCC0.CCC=0x0000;
TCC0.CCD=0x0000;

// Restore interrupts enabled/disabled state
SREG=s;
}

.........................

     EN=TCC0.CNT;    //var int EN

My encoder 1000 puls/revolution.

Thank for help :)

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

Quote:

I output timer counter values into LCD.

Presumably using code you haven't shown? Don't you think it might be an idea to show both the counter handling code and also the output code. Maybe it's not big enough for the expected counts or maybe your final output to LCD handling is in error even though it IS counting the right values. Without seeing the code no one here is going to be able to help.

BTW do you really write all your code flush-left or was the indentation lost when you posted it?

Also I see SREG being restored from a variable 's' in that but maybe my old eyes are too tired to see the place where it's actually being assigned?

PS Ah sorry I see that EN is the counter variable (it's very misleading to use all upper case for variable names!). So, being an "int" (assuming that's what the comment is suggesting) means it can hold 0..32767 (I assume the -32768..-1 part of the range won't be relevant) At 1000 counts per rev is that really going to be wide enough?

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

Can somebody post here or link for correct initilization of timers, ports for reading encoder in xmega? :)

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

Does AVR1600 not help?

www.atmel.com/dyn/resources/prod...

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

Ozhan KD
Knowledge is POWER

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

Hi! Encoder now work fine.
But using index speed measured values are randoms :(.

#include 
#include 
#include 
#include 
#include 
#include 

#define GetCaptureValue(_tc)  ( _tc.CCA )

//int mltEN=360;         
//int divEN=8192;        

volatile long int AT=0;  
volatile long int calcFreq=0;
volatile long int VE=0;  
int line_count=2048;


volatile unsigned char chrspc[]=" "; //temp dlja stroki vvoda znachenii


// System Clocks initialization
void system_clocks_init(void)
{
unsigned char n,s;

// Optimize for speed
#pragma optsize- 
// Save interrupts enabled/disabled state
s=SREG;
// Disable interrupts
#asm("cli")

// Internal 32 MHz RC oscillator initialization
// Enable the internal 32 MHz RC oscillator
OSC.CTRL|=OSC_RC32MEN_bm;



// Event System initialization
void event_system_init(void)
{
// Event System Channel 0 source: Port D, Pin0
EVSYS.CH0MUX=EVSYS_CHMUX_PORTD_PIN0_gc;
// Event System Channel 1 source: Port D, Pin2
EVSYS.CH1MUX=EVSYS_CHMUX_PORTD_PIN2_gc;
// Event System Channel 2 source: Port D, Pin0
EVSYS.CH2MUX=EVSYS_CHMUX_PORTD_PIN0_gc;
// Event System Channel 3 source: None
EVSYS.CH3MUX=EVSYS_CHMUX_OFF_gc;
// Event System Channel 4 source: None
EVSYS.CH4MUX=EVSYS_CHMUX_OFF_gc;
// Event System Channel 5 source: None
EVSYS.CH5MUX=EVSYS_CHMUX_OFF_gc;
// Event System Channel 6 source: None
EVSYS.CH6MUX=EVSYS_CHMUX_OFF_gc;
// Event System Channel 7 source: None
EVSYS.CH7MUX=EVSYS_CHMUX_OFF_gc;

// Event System Channel 0 source: Port D, Pin0

EVSYS.CH0CTRL=EVSYS_QDEN_bm|EVSYS_DIGFILT_2SAMPLES_gc|EVSYS_QDIRM_10_gc|EVSYS_QDIEN_bm;


// Event System Channel 1 Digital Filter Coefficient: 2 Samples
EVSYS.CH1CTRL=EVSYS_QDIEN_bm|EVSYS_DIGFILT_2SAMPLES_gc;




// Event System Channel 2 Digital Filter Coefficient: 2 Samples
EVSYS.CH2CTRL=(EVSYS.CH2CTRL & (~(EVSYS_QDIRM_gm | EVSYS_QDIEN_bm | EVSYS_QDEN_bm | EVSYS_DIGFILT_gm))) |
	EVSYS_DIGFILT_4SAMPLES_gc;
// Event System Channel 3 Digital Filter Coefficient: 1 Sample
EVSYS.CH3CTRL=EVSYS_DIGFILT_1SAMPLE_gc;
// Event System Channel 4 Digital Filter Coefficient: 1 Sample
EVSYS.CH4CTRL=(EVSYS.CH4CTRL & (~(EVSYS_QDIRM_gm | EVSYS_QDIEN_bm | EVSYS_QDEN_bm | EVSYS_DIGFILT_gm))) |
	EVSYS_DIGFILT_1SAMPLE_gc;
// Event System Channel 5 Digital Filter Coefficient: 1 Sample
EVSYS.CH5CTRL=EVSYS_DIGFILT_1SAMPLE_gc;
// Event System Channel 6 Digital Filter Coefficient: 1 Sample
EVSYS.CH6CTRL=EVSYS_DIGFILT_1SAMPLE_gc;
// Event System Channel 7 Digital Filter Coefficient: 1 Sample
EVSYS.CH7CTRL=EVSYS_DIGFILT_1SAMPLE_gc;


// PORTD initialization
// OUT register
PORTD.OUT=0x00;
PORTD.DIRCLR=0x07;
PORTD.PIN0CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_LEVEL_gc;
/////PORTD.PIN1CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_LEVEL_gc;

PORTD.PIN1CTRL=PORT_OPC_TOTEM_gc|PORT_ISC_LEVEL_gc; // QDPH90
PORTD.PIN2CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc;
PORTD.PIN3CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc;
PORTD.PIN4CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc;
PORTD.PIN5CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc;
PORTD.PIN6CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc;
PORTD.PIN7CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc;
PORTD.INTCTRL=(PORTD.INTCTRL & (~(PORT_INT1LVL_gm | PORT_INT0LVL_gm))) |
	PORT_INT1LVL_OFF_gc | PORT_INT0LVL_OFF_gc;
PORTD.INT0MASK=0x00;
PORTD.INT1MASK=0x00;

// Disable a Timer/Counter type 0
void tc0_disable(TC0_t *ptc)
{
// Timer/Counter off
ptc->CTRLA=(ptc->CTRLA & (~TC0_CLKSEL_gm)) | TC_CLKSEL_OFF_gc;
// Issue a reset command
ptc->CTRLFSET=TC_CMD_RESET_gc;
}

// Timer/Counter TCC0 initialization
void tcc0_init(void)
{
unsigned char s;
unsigned char n;

// Note: the correct PORTC direction for the Compare Channels outputs
// is configured in the ports_init function

// Save interrupts enabled/disabled state
s=SREG;
// Disable interrupts
#asm("cli")

// Disable and reset the timer/counter just to be sure
tc0_disable(&TCC0);
// Clock source: Peripheral Clock/1
TCC0.CTRLA=(TCC0.CTRLA & (~TC0_CLKSEL_gm)) | TC_CLKSEL_DIV1_gc;
// Mode: Normal Operation, Overflow Int./Event on TOP
// Compare/Capture on channel A: Off
// Compare/Capture on channel B: Off
// Compare/Capture on channel C: Off
// Compare/Capture on channel D: Off
TCC0.CTRLB=(TCC0.CTRLB & (~(TC0_CCAEN_bm | TC0_CCBEN_bm | TC0_CCCEN_bm | TC0_CCDEN_bm | TC0_WGMODE_gm))) |
	TC_WGMODE_NORMAL_gc;

// Capture event source: Event Channel 0
// Capture event action: Quadrature Decode
TCC0.CTRLD=(TCC0.CTRLD & (~(TC0_EVACT_gm | TC0_EVSEL_gm))) |
	TC_EVACT_QDEC_gc | TC_EVSEL_CH0_gc;

// Overflow interrupt: Disabled
// Error interrupt: Disabled
TCC0.INTCTRLA=(TCC0.INTCTRLA & (~(TC0_ERRINTLVL_gm | TC0_OVFINTLVL_gm))) |
	TC_ERRINTLVL_OFF_gc | TC_OVFINTLVL_OFF_gc;

// Compare/Capture channel A interrupt: Medium Level
// Compare/Capture channel B interrupt: Medium Level
// Compare/Capture channel C interrupt: Medium Level
// Compare/Capture channel D interrupt: Medium Level
TCC0.INTCTRLB=(TCC0.INTCTRLB & (~(TC0_CCDINTLVL_gm | TC0_CCCINTLVL_gm | TC0_CCBINTLVL_gm | TC0_CCAINTLVL_gm))) |
	TC_CCDINTLVL_MED_gc | TC_CCCINTLVL_MED_gc | TC_CCBINTLVL_MED_gc | TC_CCAINTLVL_MED_gc;


TCC0.INTFLAGS=TCC0.INTFLAGS;
TCC0.CNT=0x0000;
TCC0.PER=0x1FFF;
// Set channel A Compare/Capture register
TCC0.CCA=0x0800;      //90°
// Set channel B Compare/Capture register
TCC0.CCB=0x1000;      //180°
// Set channel C Compare/Capture register
TCC0.CCC=0x1800;      //270°
// Set channel D Compare/Capture register
TCC0.CCD=0x1FFE;      //0°

// Disable and reset the timer/counter just to be sure
tc0_disable(&TCD0);
// Clock source: Peripheral Clock/64
TCD0.CTRLA=TC_CLKSEL_DIV4_gc;
// Mode: Normal Operation, Overflow Int./Event on TOP
// Compare/Capture on channel A: Off
// Compare/Capture on channel B: Off
// Compare/Capture on channel C: Off
// Compare/Capture on channel D: Off
TCD0.CTRLB=TC0_CCAEN_bm;

// Capture event source: Event Channel 2
// Capture event action: None
TCD0.CTRLD=TC_EVACT_FRW_gc | TC_EVSEL_CH2_gc;

// Overflow interrupt: Disabled
// Error interrupt: Disabled
TCD0.INTCTRLA=(TCD0.INTCTRLA & (~(TC0_ERRINTLVL_gm | TC0_OVFINTLVL_gm))) |
	TC_ERRINTLVL_OFF_gc | TC_OVFINTLVL_OFF_gc;

TCD0.INTCTRLB=(TCD0.INTCTRLB & (~(TC0_CCDINTLVL_gm | TC0_CCCINTLVL_gm | TC0_CCBINTLVL_gm | TC0_CCAINTLVL_gm))) |
	TC_CCDINTLVL_OFF_gc | TC_CCCINTLVL_OFF_gc | TC_CCBINTLVL_OFF_gc | TC_CCAINTLVL_OFF_gc;

// Clear the interrupt flags
TCD0.INTFLAGS=TCD0.INTFLAGS;
// Set counter register
TCD0.CNT=0x0000;
// Set period register
TCD0.PER=0xFFFF;
// Set channel A Compare/Capture register
TCD0.CCA=0x0000;
// Set channel B Compare/Capture register
TCD0.CCB=0x0000;
// Set channel C Compare/Capture register
TCD0.CCC=0x0000;
// Set channel D Compare/Capture register
TCD0.CCD=0x0000;


     
// System clocks initialization
system_clocks_init();

// Event system initialization
event_system_init();
// Ports initialization
ports_init();
// Timer/Counter TCC0 initialization
tcc0_init();
// Timer/Counter TCC1 initialization
//tcc1_init();
tcd0_init();
lcd_init(16);

while (1)
{
       
    if ((TCD0.INTFLAGS & TC0_CCAIF_bm)!=  0) 
    {
        /* Period of counter ticks are 1/(F_CPU/clk_div)
        * Real tick count is 4 times captured value
        * (when used with quadratur signal).
        * Real frequency is then (F_CPU/clk_div)/(capture_value * linecount)
        * For output in RPM multiply frequency by 60 (60 sec per min).*/
        calcFreq = 2000000/((TCD0.CCA & 0xFFFC) * 2048);
        VE = calcFreq;//*60;  // not works!!!
    }                
       
}