Arduino-USB Host Shield with Bulk Transfer

Hi all,

First of all, I am new to Arduino and also new to this forum, hopefully I post this question in the right place.

I have got a Duemilanoves (ATmega168) board and a USB Host Shield from Sparkfun http://www.sparkfun.com/commerce/produc … ts_id=9628. I used the libraries from http://www.circuitsathome.com/category/ … usb-shield and have changed the .h file according to the Sparkfun website. I tried the example sketch http://www.circuitsathome.com/mcu/progr … eripherals and it works fine. So I start to work on my project.

My project is to use the Arduino to talk to a power monitoring device called the “WattsUp Pro”.

https://www.wattsupmeters.com/secure/im … CORD_1.jpg

This device has a USB port and I can get information through my computer, by using pyserial with python. In general, you issue a command such as “#D,R,0;” to the device and it will feed back the measured data, eg. “#D,-,34, … ;”. I use USEB_View and get the device’s USB information as follow:

By using the USBView utility, we can get the USB connection tree of the end device.
Device Descriptor:
•	bcdUSB:		0x0200
•	bDeviceClass:		0x00
•	bDeviceSubClass:	0x00
•	bDeviceProtocol:	0x00
•	bMaxPacketSize0:	0x08 (8)
•	idVendor:		0x0403 (Future Technology Devices International Limited)
•	idProduct:		0x6001
•	bcdDevice:		0x0600
•	iManufacturer:		0x01
•	0x0409:			"FTDI"
•	iProduct:		0x02
•	0x0409:			"FT232R USB UART"
•	0x0409:			"FT232R USB UART"
•	iSerialNumber:		0x03
•	0x0409:			"A7005chz"
•	bNumConfigurations:	 0x01
•	ConnectionStatus:	DeviceConnected
•	Current Config Value:	0x01
•	Device Bus Speed:	Full
•	Device Address:		0x01
•	Open Pipes:		2
Endpoint Descriptor:
•	bEndpointAddress:	0x81  IN
•	Transfer Type:		Bulk
•	wMaxPacketSize:	0x0040 (64)
•	bInterval:		0x00
Endpoint Descriptor:
•	bEndpointAddress:	0x02  OUT
•	Transfer Type:		Bulk
•	wMaxPacketSize:	0x0040 (64)
•	bInterval:		0x00

Configuration Descriptor:
•	wTotalLength:		 0x0020
•	bNumInterfaces:	0x01
•	bConfigurationValue:	0x01
•	iConfiguration:		 0x00
•	bmAttributes:		 0xA0 (Bus Powered Remote Wakeup)
•	MaxPower:		 0x2D (90 Ma)
Interface Descriptor:
•	bInterfaceNumber:	 0x00
•	bAlternateSetting:	 0x00
•	bNumEndpoints:	 0x02
•	bInterfaceClass:		 0xFF
•	bInterfaceSubClass:	 0xFF
•	bInterfaceProtocol:	0xFF
•	iInterface:		0x02
•	0x0409:			"FT232R USB UART"
•	0x0409:			"FT232R USB UART"
Endpoint Descriptor:
•	bEndpointAddress:	0x81  IN
•	Transfer Type:		Bulk (Attr 02)
•	wMaxPacketSize:	0x0040 (64)
•	bInterval:		0x00
Endpoint Descriptor:
•	bEndpointAddress:	0x02  OUT
•	Transfer Type:		Bulk (Attr 02)
•	wMaxPacketSize:	0x0040 (64)
•	bInterval:		0x00

And I tried to write a program to ask the device for data and the code is as follow (I modified the ps3 interface code from circuit@home):

#include <Spi.h>
#include <Max3421e.h>
#include <Max3421e_constants.h>
#include <Usb.h>
#include <avr/pgmspace.h>

#define WATTSUP_CONFIGURATION  1
#define WATTSUP_ADDR    0x01
#define WATTSUP_VID    0x0403
#define WATTSUP_PID    0x6001
#define WATTSUP_NUM_EP    3
#define EP_MAXPKTSIZE    64
#define EP_BULK    0x02
#define EP_POLL    0x01
#define CONTROL_PIPE    0
#define INPUT_PIPE    1
#define OUTPUT_PIPE    2
#define DEV_DESCR_LEN    32

#define WATTSUP_CLEAR_COMMAND_LEN    7
#define WATTSUP_HEADER_COMMAND_LEN    7


#define statusDeviceConnected 0x01
#define statusUSBConfigured 0x02
#define statusWATTSUPConnected 0x04
#define statusReportReceived 0x08

char buf[64] = {0};    //Gemeral purpose buffer for USB data
static unsigned char wattsup_status;

prog_char clear_command[] PROGMEM = {0x23,0x52,0x2C,0x57,0x2C,0x30,0x3B};
prog_char header_command[] PROGMEM = {0x23,0x44,0x2C,0x52,0x2C,0x30,0x3B};


void setup();
void loop();

EP_RECORD ep_record[WATTSUP_NUM_EP];
MAX3421E Max;
USB Usb;


void setup(){
  byte tmpdata = 0;
  Serial.begin(115200);
  Serial.println("Start");
  Max.powerOn();
  delay(200);
}

void loop(){
  Max.Task();
  Usb.Task();
  if(Usb.getUsbTaskState() == USB_DETACHED_SUBSTATE_INITIALIZE){
    Serial.println("USB_DETACHED_SUBSTATE_INITIALIZE");
    wattsup_status = 0;  
  }
  if(Usb.getUsbTaskState() == USB_STATE_CONFIGURING) {  
    Serial.println("START TO INIT");
    WATTSUP_init();
    if(wattsup_status & statusWATTSUPConnected){
      Serial.println(wattsup_status & statusWATTSUPConnected, HEX);
      Usb.setUsbTaskState(USB_STATE_RUNNING);
    }
  }
  
  if(Usb.getUsbTaskState() == USB_STATE_RUNNING){
    Serial.println("Polling");
    WATTSUP_poll();
  }
}

void WATTSUP_init(void){
  Serial.println("INSIDE THE INIT LOOP");
  byte rcode = 0;
  byte i;
  USB_DEVICE_DESCRIPTOR* device_descriptor;
  wattsup_status = statusDeviceConnected;
  
  ep_record[CONTROL_PIPE] = *(Usb.getDevTableEntry(0,0));  //copy Endpoint Zero
  //make sure if the ep_record[Control Pipe] is good
  
  ep_record[OUTPUT_PIPE].epAddr = 0x02;
  ep_record[OUTPUT_PIPE].Attr = EP_BULK;
  ep_record[OUTPUT_PIPE].MaxPktSize = EP_MAXPKTSIZE;
  ep_record[OUTPUT_PIPE].Interval = EP_POLL;
  ep_record[OUTPUT_PIPE].sndToggle = bmSNDTOG0;
  ep_record[OUTPUT_PIPE].rcvToggle = bmRCVTOG0;

  ep_record[INPUT_PIPE].epAddr = 0x81;
  ep_record[INPUT_PIPE].Attr = EP_BULK;
  ep_record[INPUT_PIPE].MaxPktSize = EP_MAXPKTSIZE;
  ep_record[INPUT_PIPE].Interval = EP_POLL;
  ep_record[INPUT_PIPE].sndToggle = bmSNDTOG0;
  ep_record[INPUT_PIPE].rcvToggle = bmRCVTOG0;
  
  Usb.setDevTableEntry(WATTSUP_ADDR, ep_record);
  
  rcode = Usb.getDevDescr(WATTSUP_ADDR, ep_record[CONTROL_PIPE].epAddr, DEV_DESCR_LEN, (char *)&buf);
  if(rcode){
    Serial.println("Cannot get Descriptor");
    return;
  }
  device_descriptor = (USB_DEVICE_DESCRIPTOR *) &buf;
  if((device_descriptor->idVendor != WATTSUP_VID) || (device_descriptor->idProduct != WATTSUP_PID)){
    Serial.println("The End Device Is Unknown.");
    return;
  }
  Serial.println("Succeed");
    
  rcode = Usb.setConf(WATTSUP_ADDR, ep_record[CONTROL_PIPE].epAddr, WATTSUP_CONFIGURATION );
  if( rcode ) return;
  wattsup_status |= statusUSBConfigured;
  Serial.println("Configured");
    
  WATTSUP_request();
  Serial.println("Connected");
  
  delay(200);  
}

void WATTSUP_request(void){
  byte rcode = 0;
  byte i = 0;
  char buf[64] = {0};
  for (i=0; i<WATTSUP_CLEAR_COMMAND_LEN; i++) {
    buf[i] = pgm_read_byte_near(clear_command+i);
  }
  rcode = Usb.outTransfer(WATTSUP_ADDR, ep_record[OUTPUT_PIPE].epAddr, WATTSUP_CLEAR_COMMAND_LEN, buf);
  for( i = 0; i < WATTSUP_CLEAR_COMMAND_LEN; i++ ) {
    Serial.print( buf[i]);
  }
  if(rcode){
    Serial.println("Failed");
    return;
  }
  Serial.println("Issued the clear command.");
  
  delay(200);
  
  for (i=0; i<WATTSUP_HEADER_COMMAND_LEN; i++) {
    buf[i] = pgm_read_byte_near(header_command+i);
  }
  rcode = Usb.outTransfer(WATTSUP_ADDR, ep_record[OUTPUT_PIPE].epAddr, WATTSUP_HEADER_COMMAND_LEN, buf);
    for( i = 0; i < WATTSUP_CLEAR_COMMAND_LEN; i++ ) {
    Serial.print( buf[i]);
  }
  if(rcode){
    Serial.println("Failed");
    return;
  }
  Serial.println("Issued the header command.");

  wattsup_status |= statusWATTSUPConnected;
  delay(200);
  return;
}


void WATTSUP_poll(void){
  char buf[0x0040] = { 0 };      //keyboard buffer
  byte i = 0;
  byte rcode = 0;
  
  rcode = Usb.inTransfer(WATTSUP_ADDR, ep_record[INPUT_PIPE].epAddr, 8, buf);
  
  if(rcode){
    Serial.println("Failed polling");
    return;
  }
  
  for( i = 0; i < 0x0040; i++ ) {
       Serial.print( buf[i]);
  }
  
  return;
}

Now, first of all, I dont know if I am doing the correct thing to start a bulk out transfer, furthermore, I dont know if I have the setting or procedure correct. The bottom line is, I cannot get any data from the device. Wondering if anyone has any idea what I have done wrong. Thanks so much.

-klo