(SOLUCIONADO) Ayuda a un novato. Problema con Leonardo y ATMEL STUDIO

Hola a todos.

Me presento como el nuevo novato del foro. He empezado a meterme en este mundillo y poco a poco quiero ir avanzando y aprendiendo.

Al grano, tengo una placa Leonardo, ya he hecho mis primeras "cosillas" con tutoriales que veo por internet.

Hace unos días vi una aplicación de Arduino + GPS. El código en cuestión está hecho en ATMEL STUDIO. Me descargué el código y también el software ATMEL. Pero aquí vienen los problemas. Al intentar cargar el programa en la placa me es imposible hacerlo, sale un mensaje que dice:

Error 1 unrecognized command line option '-Wl' avr-g++.exe

y aquí me quedo estancado. He probado hacer en ATMEL el programa "Blink" y me funciona correctamente.

¿Sabe alguien cómo puedo solucionarlo?

Gracias a todos por vuestra ayuda.

Subí el código usando los tags (el nro 11)

Se trata de simular la velocidad con un modulo GPS y el arduino. El GPS da la posición, el arduino procesa esa posición y saca una señal, que con un transistor externo la convierto en valores 0v o 5v.

Es como si ese 0v o 5v lo diera una ruleta girando con un imán sobre un sensor hall fijo. Ese 0v o 5v lo necesita el display que me marca la velocidad.

Este es el código:

#define F_CPU 16000000L
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>    // including the average delay lib
#include <SoftwareSerial.h>
#include "led.h" // Header file for led
#include "usart.h" // Header for Serial communication

#define MYDEBUG(x)

// OBJECT CREATION
LED led1(0x05,5); // Creates an object called led1 connected to PortB.5 (0x05 is the Special function register for PORTB)
LED output(0x0b,4);  //PPRTD, bit 4

SoftwareSerial mySerial(2, 3,false);
#include <avr/io.h>
#include <avr/interrupt.h>

#define FOSC F_CPU // Clock Speed
#define BAUD 115200  // Baud Rate
#define MYUBRR (((((FOSC * 10) / (16L * BAUD)) + 5) / 10) - 1)

// NMEA sentences
#define NMEA_DISABLE_CGA "PSRF103,00,00,00,01"
#define NMEA_DISABLE_GLL "PSRF103,01,00,00,01"
#define NMEA_DISABLE_GSA "PSRF103,02,00,00,01"
#define NMEA_DISABLE_GSV "PSRF103,03,00,00,01"
#define NMEA_DISABLE_RMC "PSRF103,04,00,00,01"
#define NMEA_DISABLE_VTG "PSRF103,05,00,00,01"
#define NMEA_ENABLE_VTG_1HZ "PSRF103,05,00,01,01"
#define NMEA_QUERY_VTG "PSRF103,05,01,01,01"

char nmea_data[128];
#define STAT_NMEA_NONE 0
#define STAT_NMEA_HEADER 1
#define STAT_NMEA_DATA 2
 
// VTG-Course Over Ground and Ground Speed
//$GPVTG,309.62,T,,M,0.13,N,0.2,K
char nmea_header[5];
char nmea_field[32]; 
long knots=1000L,tknots;
int dotpos;
#define KNOT_FACTOR_H 2626000L
#define KNOT_FACTOR_L 164125L
#define KNOT_LOWER_THRESHOLD 300L //below 3 knots
#define KNOT_UPPER_THRESHOLD 500L //over 5 knots
#define INIT_TIMER_COUNT 6
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT

int ledPin = 13;
int int_counter = 0;
int on=0;
/* Timer2 reload value, globally available */  
unsigned int tcnt2;  
int pwm_high=-1;
 char setnyb(unsigned char c)
{
  if(c<9) return c+'0';
  else return c-10+'A';
}

void send_nmea(const char *datagram) {
 int i;
 char *p=(char*)datagram;
 unsigned char checksum=0;
 i=0;
 nmea_data[i++]='

Gracias por la ayuda.

;
while(*p) {
nmea_data[i]=p++;
checksum=checksum^nmea_data[i];
i++;
}
nmea_data[i++]='
';
nmea_data[i++]=setnyb((checksum >> 4) &0x0f);
nmea_data[i++]=setnyb(checksum &0x0f);
nmea_data[i]=0x00;
mySerial.println((const String &)nmea_data);

}

void pwm_set(long OCRValue)
{
OCR1A = OCRValue;                          // set the counter
}

void pwm_start(int high_low)
{
if(high_low)
TCCR1B = _BV(WGM12)|_BV(CS11)|_BV(CS10);   //              // CTC mode - 64 prescale
else
TCCR1B = _BV(WGM12)|_BV(CS12)|_BV(CS10);   //              // CTC mode - 256 prescale
TCCR1A = _BV(COM1A0);                      //              // Toggle mode 0C1A  
pwm_high=high_low;
}

void pwm_stop(void)
{
TCCR1B &= ~(1<<CS12);             // Clear bit  
TCCR1B &= ~(1<<CS10);             // Clear bit  
}

void set_tknots(long knots)
{
if(knots > 0) {
if(pwm_high==1) {
if(knots > KNOT_LOWER_THRESHOLD) {
tknots=KNOT_FACTOR_H/knots;
pwm_set(tknots);
} else {
tknots=KNOT_FACTOR_L/knots;
pwm_start(0);
pwm_set(tknots);
}
}
else if(pwm_high==0) {
if(knots < KNOT_UPPER_THRESHOLD) {
tknots=KNOT_FACTOR_L/knots;
pwm_set(tknots);
} else {
tknots=KNOT_FACTOR_H/knots;
pwm_start(1);
pwm_set(tknots);
}
} else {
tknots=KNOT_FACTOR_L/knots;
pwm_start(0);
pwm_set(tknots);
}
}
else {
pwm_high=-1;
pwm_stop();
}
}
void restart_vtg(void)
{
led1.on();
_delay_ms(100);
send_nmea(NMEA_QUERY_VTG);  
led1.off();
}
int main(void)
{
char c,*p;
unsigned char stat=STAT_NMEA_NONE;
int head_counter,nmea_field_counter,nmea_field_data_counter;
int delay_counter=0;
// INITIALIZATIONS
DDRB = 0b00100010; //B5 output: board LED B2 OC1 output
USART_Init(MYUBRR); // Initializes the serial communication

mySerial.begin(4800);
mySerial.listen();
set_tknots(knots);
_delay_ms(10000);
sei();
   send_nmea(NMEA_DISABLE_CGA);
send_nmea(NMEA_DISABLE_GLL);
send_nmea(NMEA_DISABLE_GSA);
send_nmea(NMEA_DISABLE_GSV);
send_nmea(NMEA_DISABLE_RMC);
send_nmea(NMEA_DISABLE_VTG);
send_nmea(NMEA_DISABLE_VTG);
restart_vtg();
while(1)
   {
    sei();
#if 0
for(knots=0; knots < 5000L; knots+=50){
led1.on();
  set_tknots(knots);
_delay_ms(500);
led1.off();
}
#endif
if (mySerial.available()) {
c=mySerial.read();
MYDEBUG(USART_Sendbyte(c));
if( c < 0x20) {
stat=STAT_NMEA_NONE;
}
if( c == 0x0a) {
restart_vtg();
}
switch (stat) {

case STAT_NMEA_HEADER:
if(head_counter < 5 ) {
nmea_header[head_counter++] = c;
if(head_counter==5) {
if(strncmp(nmea_header,"GPVTG",5) ==0) {
MYDEBUG(USART_Send_string("GPVTG\r\n"));
stat=STAT_NMEA_DATA;
nmea_field_counter=0;
head_counter=0;
} else {
stat=STAT_NMEA_NONE;
}
}
} else {
stat=STAT_NMEA_NONE;
}

break;
case STAT_NMEA_DATA:
if(c == ',') {
if(nmea_field_counter==5) {
p=nmea_field;
dotpos=0;
knots=0;
while(*p) {
if(*p >= '0' && p <= '9') {
knots=knots
10L+*p-'0';
}
p++;
}
// sprintf(nmea_field,"\r\nspeed=%d\n\r",(int)knots);
// USART_Send_string(nmea_field);
    set_tknots(knots);
delay_counter=0;
}

nmea_field_counter++;
nmea_field_data_counter=0;
nmea_field[0]=0;
}
if(nmea_field_counter==5) {
nmea_field[nmea_field_data_counter++]=c;
nmea_field[nmea_field_data_counter]=0;
}
break;
case STAT_NMEA_NONE:
default:
delay_counter++;
_delay_ms(100);
if(delay_counter>100) { //10 seconds
delay_counter=0;
restart_vtg();
}
if(c=='


Gracias por la ayuda.

) {
 stat=STAT_NMEA_HEADER;
 head_counter=0;
 }
 break;
 }
 }
    }
}

Gracias por la ayuda.

no esta completo el código porque tienes muchos header (.h) que no dispongo asi que favor de publicar el link.
Veo que esta hecho por alguien que viene usando mucho ATMEL STUDIO.

Perdón, adjunto el zip con el código completo

GPS2airmar.zip (151 KB)

bueno te copio el resultado del archivo modificado para Arduino compatible con las versiones actuales.

Compiling 'GPS2airmar2' for 'Arduino Uno'
Build folder: file:///C:/Users/Bichy/AppData/Local/VMicro/Arduino/Builds/GPS2airmar2/uno
Binary sketch size: 6.296 bytes (used 20% of a 32.256 byte maximum) (12,23 secs)
Minimum Memory Usage: 472 bytes (23% of a 2048 byte maximum)

No pude hacerlo funcionar tal como estaba asi que lo volví Arduino compatible setup() y loop() en lugar del clasico main()
esta todo el proyecto que llama GPS2airmar2 y esta comprimido .ZIP

GPS2airmar2.zip (299 KB)

Muchisimas gracias surbyte.

Me tengo que bajar la versión 6.2 del ATMEL STUDIO ya que la que tengo es la 6.1 y no me deja abrirlo.

Ya te comentaré.

Perdona.. siempre tengo actualizadas las herramientas.

Hola surbyte,

he cargado y configurado la version 6.2 del ATMEL. He probado con el código "blink" y funciona perfectamente.

Pero con el código GPS2airmar2 no me funciona. Al pulsar F7 (Build solution) me sale el siguiente error:

Compiling 'GPS2airmar2' for 'Arduino Leonardo'
usart.cpp:In function 'void USART_Init(unsigned int)'
usart.cpp:16: error: 'UBRR0H' was not declared in this scope
usart.cpp:17: error: 'UBRR0L' was not declared in this scope
usart.cpp:19: error: 'UCSR0B' was not declared in this scope
usart.cpp:19: error: 'RXEN0' was not declared in this scope
usart.cpp:19: error: 'TXEN0' was not declared in this scope
usart.cpp:21: error: 'UCSR0C' was not declared in this scope
usart.cpp:21: error: 'USBS0' was not declared in this scope
usart.cpp:21: error: 'UCSZ00' was not declared in this scope
usart.cpp:In function 'void USART_Sendbyte(unsigned char)'
usart.cpp:30: error: 'UCSR0A' was not declared in this scope
usart.cpp:30: error: 'UDRE0' was not declared in this scope
usart.cpp:33: error: 'UDR0' was not declared in this scope
usart.cpp:In function 'unsigned char USART_Receive()'
usart.cpp:57: error: 'UCSR0A' was not declared in this scope
usart.cpp:57: error: 'RXC0' was not declared in this scope
usart.cpp:60: error: 'UDR0' was not declared in this scope
SoftwareSerial.cpp:59: warning: only initialized variables can be placed into program memory area
Error compiling

¿Qué puede estar pasando? Igual tengo algo mal configurado?

Yo veo esto en mi explorador del proyecto

coincide con lo que ves en tu ATMEL STUDIO?
dejando de lado el visual Micro que si vas a seguir trabajando con arduino te lo recomiendo. Lo puedes probar x 30 dias y luego hay que comprarlo.

Te paso foto adjunta de lo que veo en mi explorador.

Coincide en todo excepto los símbolos del fichero led.cpp y usart.cpp. En mi caso en los iconos aparecen los símbolos C++ en ambos ficheros. EL resto de ficheros que cuelgan del directorio del Visual Micro tambien tienen el icono un poco distinto, en el caso del fichero GPS2airmar2.ino es una hoja en blanco. En la foto que te adjunto se ve la diferencia.

¿Es necesario tener el Visual Micro para poder cargar el código hecho en Atmel Studio en el Arduino? Solo me ha tocado hacer con el Ide de Arduino.

Gracias y perdona por tanta pregunta.

No hay problema por las preguntas.
te voy a enviar un MP

Bueno, como te dije hoy temprano resulto muy interesante.
Voy a poner la solucion aca pero luego si quieres hacemos como hoy temprano y lo instalo en tu pc.

El problema es justamente usart.cpp que esta hecha para ATmega328

entonces comparando Registros del procesador ATmega32U4 contra el ATmega328P me di cuenta que no hablabamos de lo mismo y que no era configuración sino definición de registros.

La librería usart.cpp para Leonardo queda asi por ahora (hay dos rutinas la que envía y la que recibe que debemos probar).

/*
 * usart.cpp
 *
 * Created: 07/12/2011 15:17:35
 *  Author: Boomber
 *  Modified: 12/04/2014 11:30:00
 *  Modificada para Leonardo : Ricardo Callejo
 */ 
#include "usart.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h> // Conversions

void USART_Init( unsigned int ubrr)
{
///*Set baud rate */
//UBRR0H = (unsigned char)(ubrr>>8);
//UBRR0L = (unsigned char)ubrr;
////Enable receiver and transmitter */
//UCSR0B = (1<<RXEN0)|(1<<TXEN0);
///* Set frame format: 8data, 2stop bit */
//UCSR0C = (1<<USBS0)|(3<<UCSZ00);

  // Set the Baud rate
  UBRR1H = (unsigned char)(ubrr>>8);
  UBRR1L = (unsigned char)ubrr;
  // Enable bidirectional UART
  UCSR1B |= _BV(RXEN1) | _BV(TXEN1);
  // Use 8-bit characters
  UCSR1C |= _BV(UCSZ10) | _BV(UCSZ11);
}




void USART_Sendbyte( unsigned char data ) {
///* Wait for empty transmit buffer */
//while ( !( UCSR0A & (1<<UDRE0)) )
//;
///* Put data into buffer, sends the data */
//UDR0 = char(data);

  // Wait to be able to transmit
  while(!(UCSR1A & _BV(UDRE1)))
       asm volatile("nop"::);
  // Put the data into the send buffer
  UDR1 = char(data);

}

void USART_Send_string(const char *str){

      while (*str) 
      USART_Sendbyte(*str++);
 
}

void USART_Send_int(unsigned int d ) {
 char str[10];
 sprintf(str,"%u",d);
 USART_Send_string(str);
 
}


unsigned char USART_Receive( void ) {
///* Wait for data to be received */
//while ( !(UCSR0A & (1<<RXC0)) )
//;
///* Get and return received data from buffer */
//return UDR0;

  while (!(UCSR1A & _BV(RXC1)) );
  return UDR1;
}

Si modificas eso en usart.cpp todo funcionará como estaba.
Adjunto archivo.

usart.cpp (1.06 KB)

Hola a todos,

Despues de varias pruebas, pude ponerme en contacto con el creador del código y se dio cuenta que el problema estaba en las rutas de acceso de los ficheros. Atmel Studio tiene que encontrar los header y hay que darle las rutas correctas de dónde se encuentran. Fallo mío por no darme cuenta antes.

Pues nada, espero que sirva para los demás.

Mil gracias, Surbyte por tu ayuda.