Joystick - Atmega8 - Atmega644p - roboclaw

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

 

Hello guys, Im trying to read a joystick via ADC with Atmega8 and send via usart to atmega644p, and then send to pc (the main goal is to send to roboclaw 2x15a)

I send the values directly atmega8 to pc and its ok, but when i send via atmega644p sometimes x and y have the same value.

 

joystick code

/* Created: 26/09/2017 11:58:03
 * Author : Eduardo Pilar
 */ 
 // Atmega 8, @16Mhz

#include <avr/interrupt.h>
#include <stdio.h>
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <util/delay.h>
#define USART_BAUDRATE 9600
#define BAUD_PRESCALER (((F_CPU) / (USART_BAUDRATE * 16UL))-1)

void initADC(void)
{
	ADMUX |=(1<<REFS0); /* Utiliza VCC como Ref */
	ADCSRA |=(1<<ADEN)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2); /* ADEN enable do ADC, 128 Prescaler*/
	

}

uint16_t read_adc(uint8_t ch)
{	
	
	//ch &= 0b00000111; // escolhe o canal
	ADMUX = (ADMUX & 0xF8)|(ch&7);
	ADCSRA|=(1<<ADSC); //Inicia conversao
	while(!(ADCSRA&(1<<ADSC))); //espera pelo fim da conversao
	return(ADC);
	
}

void initUSART(void)
{
	
	UBRRH=(BAUD_PRESCALER>>8);
	UBRRL= BAUD_PRESCALER; //valor relativo ao baud rate de 9600
	UCSRA=0x00;
	UCSRB=(1<<RXEN)|(1<<TXEN); // hablita transmissao e recepcao 
	UCSRC=(1<<URSEL)|(1<<USBS)|(3<<UCSZ0); // 2 stops bit, 8 bit data

}


unsigned char receiveusart(void)
{
	while(!(UCSRA&(1<<RXC)));
	return UDR;
	
}

void send_usart ( uint8_t data)
{

	while((UCSRA & (1<<UDRE))==0);
	UDR = data;
}

void send_buffer(uint8_t x, uint8_t y)
{

	//Preparar o dados de x e y para enviar
	uint8_t joystick_enviar[2];
	joystick_enviar[0] = x;
	joystick_enviar[1] = y ;

	
	send_usart(joystick_enviar[0]);
	send_usart(joystick_enviar[1]);
}

int main(void)
{
	
	int x,y;
	initUSART();
	initADC();

	


    while (1) 
    { 
		
		x = (uint8_t)(read_adc(0)>>2);
		_delay_ms(1);
		y = (uint8_t)(read_adc(1)>>2);
		_delay_ms(1);
		send_buffer(x,y);
		
 		
		

	}

}

Atmega644p Code

/*
 * GccApplication3.c
 *
 * Created: 11/10/2017 11:50:13
 * Author : Eduardo Pilar
 */

#include <avr/interrupt.h>
#include <stdio.h>
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <util/delay.h>
#define USART_BAUDRATE 9600
#define BAUD_PRESCALER (((F_CPU) / (USART_BAUDRATE * 16UL))-1)


void initusart1(void)
{
	UBRR1H = (BAUD_PRESCALER >> 8);
	UBRR1L = BAUD_PRESCALER; //valor relativo ao baud rate de 9600
	UCSR1A = 0x00;
	UCSR1B=(1<<RXEN1)|(1<<TXEN1);//hablita transmissao e recpcao
	UCSR1C|=(1<<USBS1)|(1<<UCSZ10)|(1<<UCSZ11);// 2 stops bit, 8 bit data
	

}

void initusart0(void)
{
	UBRR0L=(BAUD_PRESCALER >> 8);
	UBRR0L= BAUD_PRESCALER; //valor relativo ao baud rate de 9600
	UCSR0B=(1<<RXEN0)|(1<<TXEN0);//hablita transmissao e recpcao
	UCSR0C|=(1<<USBS0)|(1<<UCSZ00)|(1<<UCSZ01);// 2 stops bit, 8 bit data
}

unsigned int receiveusart1(void)
{
	while(!(UCSR1A&(1<<RXC1)));
	return UDR1 ;
	
}

void send_usart0 (unsigned char data){
	while(!(UCSR0A & (1<<UDRE0)));
	UDR0 = data;
}

enum {
	M1FORWARD = 0,
	M1BACKWARD = 1,
	SETMINMB = 2,
	SETMAXMB = 3,
	M2FORWARD = 4,
	M2BACKWARD = 5,
	M17BIT = 6,
	M27BIT = 7,
	MIXEDFORWARD = 8,
	MIXEDBACKWARD = 9,
	MIXEDRIGHT = 10,
	MIXEDLEFT = 11,
	MIXEDFB = 12,
	MIXEDLR = 13,
	GETM1ENC = 16,
	GETM2ENC = 17,
	GETM1SPEED = 18,
	GETM2SPEED = 19,
	RESETENC = 20,
	GETVERSION = 21,
	SETM1ENCCOUNT = 22,
	SETM2ENCCOUNT = 23,
	GETMBATT = 24,
	GETLBATT = 25,
	SETMINLB = 26,
	SETMAXLB = 27,
	SETM1PID = 28,
	SETM2PID = 29,
	GETM1ISPEED = 30,
	GETM2ISPEED = 31,
	M1DUTY = 32,
	M2DUTY = 33,
	MIXEDDUTY = 34,
	M1SPEED = 35,
	M2SPEED = 36,
	MIXEDSPEED = 37,
	M1SPEEDACCEL = 38,
	M2SPEEDACCEL = 39,
	MIXEDSPEEDACCEL = 40,
	M1SPEEDDIST = 41,
	M2SPEEDDIST = 42,
	MIXEDSPEEDDIST = 43,
	M1SPEEDACCELDIST = 44,
	M2SPEEDACCELDIST = 45,
	MIXEDSPEEDACCELDIST = 46,
	GETBUFFERS = 47,
	GETPWMS = 48,
	GETCURRENTS = 49,
	MIXEDSPEED2ACCEL = 50,
	MIXEDSPEED2ACCELDIST = 51,
	M1DUTYACCEL = 52,
	M2DUTYACCEL = 53,
	MIXEDDUTYACCEL = 54,
	READM1PID = 55,
	READM2PID = 56,
	SETMAINVOLTAGES = 57,
	SETLOGICVOLTAGES = 58,
	GETMINMAXMAINVOLTAGES = 59,
	GETMINMAXLOGICVOLTAGES = 60,
	SETM1POSPID = 61,
	SETM2POSPID = 62,
	READM1POSPID = 63,
	READM2POSPID = 64,
	M1SPEEDACCELDECCELPOS = 65,
	M2SPEEDACCELDECCELPOS = 66,
	MIXEDSPEEDACCELDECCELPOS = 67,
	SETM1DEFAULTACCEL = 68,
	SETM2DEFAULTACCEL = 69,
	SETPINFUNCTIONS = 74,
	GETPINFUNCTIONS = 75,
	SETDEADBAND	= 76,
	GETDEADBAND	= 77,
	GETENCODERS = 78,
	GETISPEEDS = 79,
	RESTOREDEFAULTS = 80,
	GETTEMP = 82,
	GETTEMP2 = 83,	//Only valid on some models
	GETERROR = 90,
	GETENCODERMODE = 91,
	SETM1ENCODERMODE = 92,
	SETM2ENCODERMODE = 93,
	WRITENVM = 94,
	READNVM = 95,	//Reloads values from Flash into Ram
	SETCONFIG = 98,
	GETCONFIG = 99,
	SETM1MAXCURRENT = 133,
	SETM2MAXCURRENT = 134,
	GETM1MAXCURRENT = 135,
	GETM2MAXCURRENT = 136,
	SETPWMMODE = 148,
	GETPWMMODE = 149,
	FLAGBOOTLOADER = 255
};

//PARA ENVIAR COMANDO: Address, Command, ByteValue, CRC16
//PAG 64 - Manual

//VARIAVEL GLOBAL PARA GUARDAR O VALOR DO CRC
uint16_t m_crc;

//FUNCOES PARA CALCULO DO CRC
void crc_clear()
{
    m_crc = 0;
}

void crc_update( uint8_t data )
{
    int i;
    m_crc = m_crc ^ ((uint16_t)data << 8);
    for (i=0; i<8; i++)
    {
        if (m_crc & 0x8000)
            m_crc = (m_crc << 1) ^ 0x1021;
        else
            m_crc <<= 1;
    }
}

uint16_t crc_get()
{
    return m_crc;
}

void send_command(uint8_t address, uint8_t cmd, uint8_t valor){
	
	int i;
	
	crc_clear();
    crc_update(address);
    crc_update(cmd);
    crc_update(valor);
    uint16_t crc = crc_get();

    
    uint8_t buffer_cmd_enviar[5];
    buffer_cmd_enviar[0] = address;
    buffer_cmd_enviar[1] = cmd;
    buffer_cmd_enviar[2] = valor;
    buffer_cmd_enviar[3] = crc>>8;
    buffer_cmd_enviar[4] = crc;


	for(i=0;i<5;i++){
   
    send_usart0(buffer_cmd_enviar[i]);
	}
    
}


	
int main(void)
{
	initusart1();
	initusart0();
	uint8_t  x,y;

	uint8_t receve_joystick[2];

	//send_command(0x80,M1FORWARD,64); //127 - Velocidade max, 64 - metade da velocidade, 0 - stop

	while (1)
	{
		for(int i=0; i<2; i++){
		receve_joystick[i] = receiveusart1();
		}
			x=0;
            y=0;
			x = receve_joystick[0];
			x=x/2;
			send_usart0(x);
			//send_command(0x80,MIXEDLR,x); //127- full R, 64 stop turn, 0- full L
      _delay_ms(4000);
			y = receve_joystick[1];
			y=y/2;
			send_usart0(y);
			//send_command(0x80,MIXEDFB,y);// 127 - Full Forward, 64 Stop, 0- full backward
      _delay_ms(4000);
   		}
			  
		

	
}

I think when i do recebe_joystick[i]=receiveusart1() sometimes x stay in position 0 and other times in 1 position.

Any solution to resolve my problem?

 

best regards

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

Not the problem but:

void send_buffer(uint8_t x, uint8_t y)
{

	//Preparar o dados de x e y para enviar
	uint8_t joystick_enviar[2];
	joystick_enviar[0] = x;
	joystick_enviar[1] = y ;

	
	send_usart(joystick_enviar[0]);
	send_usart(joystick_enviar[1]);
}

What is the purpose of the array in this? Surely it would work the same as:

void send_buffer(uint8_t x, uint8_t y)
{
	send_usart(x);
	send_usart(y);
}

This may or may not relate to your problem but in one lot of code you have:

    uint8_t buffer_cmd_enviar[5];
    buffer_cmd_enviar[0] = address;
    buffer_cmd_enviar[1] = cmd;
    buffer_cmd_enviar[2] = valor;
    buffer_cmd_enviar[3] = crc>>8;
    buffer_cmd_enviar[4] = crc;


	for(i=0;i<5;i++){
   
    send_usart0(buffer_cmd_enviar[i]);
	}

which seems to very sensibly wrap up the data to send in "packets" with things like crc to protect its integrity. While elsewhere you are just doing:

void send_buffer(uint8_t x, uint8_t y)
{
	send_usart(x);
	send_usart(y);
}

and receiving with:

		for(int i=0; i<2; i++){
		receve_joystick[i] = receiveusart1();
		}

which has no such "packetisation. If the send/receive ever "miss a byte" how do you get this back in step?

 

You really need a "protocol" to pass this data. Some kind of unequivocal "data packet starts here", then "data payload" then "end of packet with option checksum". That way if communication ever breaks down you can just skip bytes that arrive until  the next "start of packet" arrives and you can use the CRC to check that the data came in unscathed.

 

Just sending x,y,x,y,x,y,x,y... probably ain't going to cut it. If I unplug the cable then plug it back in and see n,m,n,m,n,m... how do I know if 'n' is an X or a Y value?

 

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

First thought:  Why not have the '164 do the X/Y reads?

 

There isn't much going on in the Mega8 app, so the below doesn't make much difference.  But look for ADLAR in the datasheet; use that if you want an 8-bit result instead of doing the shifts.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Or (s)he did start a new thread for the new question - but didn't bother to mention it anywhere.

 

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

Clearing things up:

 

The cross-post I was pointing to was a continuation on a separate subject (by same OP). Morten has split that into a separate thread, locked that and pointed to here for continuation.

 

THIS thread you're looking at right now is the thread where the subject should be spoken about and dealt with.

 

Sorry for any confusion (and kudos to Morten for the split, lock and pointer!)

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Ok, i understand the problem. So i have to seend the data like send_comand right?

/* Created: 26/09/2017 11:58:03
 * Author : Eduardo Pilar
 */ 
 // Atmega 8, @16Mhz

#include <avr/interrupt.h>
#include <stdio.h>
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <util/delay.h>
#define USART_BAUDRATE 9600
#define BAUD_PRESCALER (((F_CPU) / (USART_BAUDRATE * 16UL))-1)

void initADC(void)
{
	ADMUX |=(1<<REFS0); /* Utiliza VCC como Ref */
	ADCSRA |=(1<<ADEN)|(1<<ADLAR)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2); /* ADEN enable do ADC, 128 Prescaler*/
	

}

uint16_t read_adc(uint8_t ch)
{	
	
	//ch &= 0b00000111; // escolhe o canal
	ADMUX = (ADMUX & 0xF8)|(ch&7);
	ADCSRA|=(1<<ADSC); //Inicia conversao
	while(!(ADCSRA&(1<<ADSC))); //espera pelo fim da conversao
	return(ADC);
	
}

void initUSART(void)
{
	
	UBRRH=(BAUD_PRESCALER>>8);
	UBRRL= BAUD_PRESCALER; //valor relativo ao baud rate de 9600
	UCSRA=0x00;
	UCSRB=(1<<RXEN)|(1<<TXEN); // hablita transmissao e recepcao 
	UCSRC=(1<<URSEL)|(1<<USBS)|(3<<UCSZ0); // 2 stops bit, 8 bit data

}


unsigned char receiveusart(void)
{
	while(!(UCSRA&(1<<RXC)));
	return UDR;
	
}

void send_usart ( uint8_t data)
{

	while((UCSRA & (1<<UDRE))==0);
	UDR = data;
}

/*void send_buffer(uint8_t x, uint8_t y)
{

	//Preparar o dados de x e y para enviar
	uint8_t joystick_enviar[2];
	joystick_enviar[0] = x;
	joystick_enviar[1] = y ;

	
	send_usart(joystick_enviar[0]);
	send_usart(joystick_enviar[1]);
}*/

//VARIAVEL GLOBAL PARA GUARDAR O VALOR DO CRC
uint16_t m_crc;


void crc_clear()
{
	m_crc = 0;
}

void crc_update( uint8_t data )
{
	int i;
	m_crc = m_crc ^ ((uint16_t)data << 8);
	for (i=0; i<8; i++)
	{
		if (m_crc & 0x8000)
		m_crc = (m_crc << 1) ^ 0x1021;
		else
		m_crc <<= 1;
	}
}

uint16_t crc_get()
{
	return m_crc;
}

void send_buffer(uint8_t x, uint8_t y){
	
	int i;
	//Calculo do CRC
	crc_clear();
	crc_update(x);
	crc_update(y);
	uint16_t crc = crc_get();

	//Preparar o dados para enviar
	uint8_t buffer_cmd_enviar[4];
	buffer_cmd_enviar[0] = x;
	buffer_cmd_enviar[1] = y;
	buffer_cmd_enviar[2] = crc>>8;
	buffer_cmd_enviar[3] = crc;


	for(i=0;i<4;i++){
		
		send_usart(buffer_cmd_enviar[i]);
		_delay_ms(1000);
	}
	
}

int main(void)
{
	
	int x,y;
	initUSART();
	initADC();
	
    while (1) 
    { 
		
		x = (uint8_t)(read_adc(1)>>2);
		_delay_ms(1);
		
		y = (uint8_t)(read_adc(0)>>2);
		_delay_ms(1);
		send_buffer(x,y);
		
 		
		

	}

}

but, how i have to do on the receiver side?

cheers