V USB HID sensor data logger
Posted: 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:
Please find the receiver code below:
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()