V USB HID sensor data logger

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
sriharir_91
Posts: 2
Joined: Mon Jun 27, 2016 5:31 pm

V USB HID sensor data logger

Post by sriharir_91 » Tue Jul 05, 2016 4:13 pm

Hi,

I am trying to design a device which logs the sensor data and presents itself as a keyboard to print out the values to a notepad.

The design is as follows: Sensor -> atmega8(transmitter) ----- (Via UART)---> atmega8(receiver) ----(via USB)---> PC

However, the code only works for the first time.. i.e., the first time i plug my device, it gets recognized and the values get typed into a notepad. But the second time i plug my device, it isn't recognized. I tried it out on different systems with the same result.

for the UART, I've used a 9600 bps baud rate.
for communicating with PC, I've used a HID protocol. (Without the UART, If I type out random values, it works all the time)

Please find the transmitter code snippet which is responsible for the UART:

Code: Select all

void ComputerDlg()
{
    unsigned char a,i;
    while(1)
    {
        a=uart_getc();
        if(a=='X')
        {
            uart_putc('X'); //// signature
         uart_putc(log_count);   
        }                 
        else if(a=='A') /// sync log memory
        {                           
            for(i=0;i<50;i++)
            {
                uart_putc(logs[i].hour);
                _delay_ms(EEPROM_DELAY);
                uart_putc(logs[i].minute);
                _delay_ms(EEPROM_DELAY);
                uart_putc(logs[i].second);
                _delay_ms(EEPROM_DELAY);
                uart_putc(logs[i].day);
                _delay_ms(EEPROM_DELAY);
                uart_putc(logs[i].month);
                _delay_ms(EEPROM_DELAY);
                uart_putc(logs[i].year);
                _delay_ms(EEPROM_DELAY);
                uart_putc(logs[i].percentage/100);
                _delay_ms(EEPROM_DELAY);
                uart_putc(logs[i].percentage%100);
                _delay_ms(EEPROM_DELAY);               
            }   
        }
        else if(a=='Z')
        {
            for(i=0;i<50;i++)
            {
                logs[i].hour=0xFF;
                _delay_ms(EEPROM_DELAY);
                logs[i].minute=0xFF;
                _delay_ms(EEPROM_DELAY);
                logs[i].second=0xFF;
                _delay_ms(EEPROM_DELAY);
                logs[i].day=0xFF;
                _delay_ms(EEPROM_DELAY);
                logs[i].month=0xFF;
                _delay_ms(EEPROM_DELAY);
                logs[i].year=0xFF;
                _delay_ms(EEPROM_DELAY);
                logs[i].percentage=0xFFFF;
                _delay_ms(EEPROM_DELAY);
            }
        }
    }
   
}


Please find the receiver code below:

Code: Select all

#define F_CPU 12000000L            //for util/delay.h
#define EEPROM_DELAY        5
#define HIDSERIAL_INBUFFER_SIZE 32

#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdlib.h>
#include <string.h>               //For parsing data into strings
#include <util/delay.h>

#include "./usbdrv/usbdrv.h"      //USB Header File
#include "./usbdrv/oddebug.h"   

uchar logs[50][8];
static uchar    reportBuffer[2];    // buffer for HID reports
static uchar    idleRate;           // in 4 ms units
int i=0;
int value=0;
int m=0;

/************************USB HID Keyboard report descriptor*************************/

PROGMEM const char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] =
{
    0x05, 0x01,                    //   USAGE_PAGE (Generic Desktop)
    0x09, 0x06,                    //   USAGE (Keyboard)
    0xa1, 0x01,                    //   COLLECTION (Application)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x08,                    //   REPORT_COUNT (8)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)s
    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
    0xc0                           //   END_COLLECTION
};

//Initialize I/O
void io_init()
{
   /******************UART initialisation********************/
   DDRD|=1<<PIND1;
   DDRD&=~(1<<PIND0);
    UCSRA=0x00;
    UCSRB=0x18;
    UCSRC=0x86;
    UBRRH=0x00;
    UBRRL=0x4D;      //BAUD RATE = 9600 bps
   
   /****************Emptying the log buffer******************/
   int a,b;
   
   for(a=0;a<50;a++)
   {
      for(b=0;b<8;b++)
      {
         logs[a][b]='\0';
      }
   }
}

//UART Transmit function
void uart_putc(uint8_t c)      
{
   while(!(UCSRA & (1 << UDRE)));
   UDR = c;
}

//UART Receive function
uint8_t uart_getc()            
{
   uint8_t b;
   while(!(UCSRA & (1 << RXC)));   //Blocking call - wait until receive buffer is full
   b = UDR;
   return b;
}

//Receive the data from main controller and buffer it in RAM
void buff_log()
{
   unsigned char a;
   
   int k=0;
   uart_putc('X');               //Handshake
   a=uart_getc();
   
   a='X';
   while (k==0)               //Polling
   {
   
      if(a=='X'||a=='x')         //Signature authentication
      {
         k=1;
         uart_putc('A');         //Sync log memory
         
         int j;
         for(j=0;j<50;j++)
         {
            logs[j][0]=uart_getc();
            logs[j][1]=uart_getc();
            logs[j][2]=uart_getc();
            logs[j][3]=uart_getc();
            logs[j][4]=uart_getc();
            logs[j][5]=uart_getc();
            logs[j][6]=uart_getc();
            logs[j][7]=uart_getc();      
         }
      
      }   //End of if() block
   }      //end of while() polling loop
   
}         //End of buff_log()

/*******************************Parsing the data into a string************************************/
static void buildReport()
{   
   memset(reportBuffer,'\0',sizeof(reportBuffer));
   
   reportBuffer[0]=0;
   if(value<=7)
   {
      reportBuffer[1]=logs[i][value];   
   }
   else if(value>7)
   {
      reportBuffer[1]=28;
   }
}
/*************************************************************************************************/

USB_PUBLIC uchar usbFunctionSetup(uchar data[8])
{
   usbRequest_t *rq = (void *)data;               //Casting the data to correct type
      
      usbMsgPtr =  reportBuffer;
      
       if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS)
      {                                    // class request type
          if(rq->bRequest == USBRQ_HID_GET_REPORT)   // wValue: ReportType (highbyte), ReportID (lowbyte)
         { 
            buildReport();                  // we only have one report type, so don't look at wValue
            return sizeof(reportBuffer);         // The entire buffer has to be sent at one shot.
         }
            
         else if(rq->bRequest == USBRQ_HID_GET_IDLE)
         {
             usbMsgPtr = &idleRate;
             return 1;
         }
         
         else if(rq->bRequest == USBRQ_HID_SET_IDLE)
         {
             idleRate = rq->wValue.bytes[1];
         }
      }
      
      else
      {
          /* no vendor specific requests implemented */
       }
      
   return 0;                           

/******************************************MAIN FUNCTION******************************************/
int main(void)
{
   int j=0;
/******************************************* Initialization***************************************/   
   io_init();
   sei();               //Enable global interrupts
   buff_log();            //To retrieve logs from the main controller unit
   odDebugInit();
   usbDeviceDisconnect();   //Enforce enumeration by disconnecting and connecting for the first time
   
   for(j=0;j<20;j++)      // 300 ms disconnect
   {   
      _delay_ms(15);
   }
   
   usbDeviceConnect();
   
   wdt_enable(WDTO_1S);   //Enable the watchdog timer
   usbInit();
   
/*******************************************Loop forever******************************************/   
   while(1)
    {   
      wdt_reset();                  //Reset the watchdog timer
      usbPoll();
       j=0;   
      if(usbInterruptIsReady()&&i<50)      // we can send another data
      {
         buildReport();
         value++;
         
         if(value>7)
         {
            i++;
            value=0;
         }
         usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
      
         if(i>=50)
         {
            i=0;
         }
      
      }
   }//End of while(1) Infinite loop

return 0;
}//End of main()

Post Reply