Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Data acquisition using PIC starter kit

Status
Not open for further replies.

engr_joni_ee

Advanced Member level 3
Joined
Nov 3, 2018
Messages
726
Helped
2
Reputation
4
Reaction score
4
Trophy points
18
Activity points
6,042
I am having my project requirement to sample the analog data at the rate of 2 Mega samples per second streaming data and send to the PC. I am thinking to use PIC starter kit with USB or Ethernet with demo software for PC side to receive and download the PIC data. I just look at some Microchip starter kits but I am not sure I can use them for my application. Any suggestion or ideas ?
 

Hi,

There is a little change in application requirement. I would have 500 kilo 12 bit samples per second and I need to send 10-12 character string with each sample to the PC. I guess USB full speed can send it to the PC. I am wondering is there any pin header on the PIC USB Starter Kit available for ADC channels ? The Microchip offers Free USB Software, is it capable to download and receive the PIC streaming data in the PC ?
 

hello,

Tell us wich MCU you want to use ..
i think it is not possible to transmit in real time at 500Ksp/sec with PIC18F
because it is allready difficult to assume 2µS/sample for the ADC itself ,
you need a minimum timing for acquistion and between each ADC sampling...

Maybe with rescent MCU, you can use ADC and DMA access
but you can not send each value in real time with 10 ascii
you send all, only when DMA Accses is finished.

USB max speed 12Mb/sec
10 char + value 16 bits => 12 chars or Bytes => 120 bits
12 000 000 / 120 =>100 000 sample /sec
+ somme bytes for the exchange protocole and USB packett=> less than 100Ksp/sec

see DSP MCU ....
 

Think about an ADC with DMA support and USB high speed or 100 Mbit Ethernet interface. Suitable CPUs are e.g. PIC32 (new MZ family has USB HS) or ARM (e.g. STM32F4xx).
 

Thanks for your reply. I guess I would go with 50 kilo sample per second at the first stage and consider USB Full Speed for communication.

- Sampling rate: 50 kilo samples per second
- String: 10 character message with each sample
- Transmission rate in bytes: (10 + 2) * 50 000 = 600 kilo bytes
- Transmission rate in bits: 6 Mega bits per second

How much is protocol overheard ? Which USB class is suitable for this application ? I realize that there is USB module on the PIC18F2550 which means that USB controller is present on the PIC18F2550, right ?. Does this means that I can directly connect the USB cable to the PIC pins D+, D-, GND ? after programming.
 

.... I realize that there is USB module on the PIC18F2550 which means that USB controller is present on the PIC18F2550, right ?. Does this means that I can directly connect the USB cable to the PIC pins D+, D-, GND ? after programming.

Yes, but ......
you need to use a HID Descriptor on PIC Side , and a HOST usb PC side
any years ago , i did some test with the MikroC HID terminal
a PIC18F2550 to send ADC measure trough USB cable , and get back some Order from the PC Terminal.

The PIC communicate with HID USB trough a commun Memory AREA in RAM
this amount of RAM is limited ..
so you can only transmit bloc per bloc, not in contineous flow data rate.
i didn't test what was the possible maximum speed of acquisition+ transfert

i think, now, 18F2550 is too old, newer PIC can get better results .. liike 18F87J50 ?


in the below example, i included the HID descriptor inside the main code..

FYI

Code:
/*
 * Project name:
    original :  HID_Read_Write_Interrupt (Testing the USB HID connection)
    revised by paulfjujo
 * Copyright:
     (c) Mikroelektronika, 2011.
 * Revision History:
     20110929 initial release (FJ);
 * Description:
     This example establishes connection with the HID terminal that is active
     on the PC. Upon connection establishment, the HID Device Name will appear
     in the respective window. After that software will wait for data and
     it will return received data back.
 * Test configuration:
     MCU:             PIC18F2550
     dev.board:  StartUSB Board 18F2550
     Oscillator:      HS, 8.000 MHz  (USB osc. is raised with PLL to 48.000MHz)
     Ext. Modules:    None.
     SW:              mikroC PRO for PIC 6.50
 * NOTES:
     (*) Be VERY careful about the configuration flags for the 18F2550 - there's
     so much place for mistake!

 */



#define CLS 12
#define BS 8
#define TAB 9
#define CR 13
#define LF 10
#define Bell 7
#define ON 0        // logique inverse avec led tiree au +5V
#define OFF 1

#define Nb_Count1 24  // 24 * 41.666mS = 1 seconde (init timer1 à 3035 et prescaler=1/8)

sbit LED_Sup at LATA1_bit;    // led rouge
sbit LED_Inf at LATB3_bit;    // led jaune   J2 enlevé et strap entre RB3 et LED3 verte


unsigned char readbuff[64] absolute 0x500;   // Buffers should be in USB RAM, please consult datasheet
unsigned char writebuff[64] absolute 0x540;


const unsigned int USB_VENDOR_ID = 0x1234;
const unsigned int USB_PRODUCT_ID = 0x1234;
const char USB_SELF_POWER = 0xC0;            // Self powered 0xC0,  0x80 bus powered
const char USB_MAX_POWER = 50;               // Bus power required in units of 2 mA
const char HID_INPUT_REPORT_BYTES = 63;
const char HID_OUTPUT_REPORT_BYTES = 63;
const char USB_TRANSFER_TYPE = 0x03;         //0x03 Interrupt
const char EP_IN_INTERVAL = 1;
const char EP_OUT_INTERVAL = 1;
const char USB_INTERRUPT = 1;
const char USB_HID_EP = 1;
const char USB_HID_RPT_SIZE = 57;

/* Device Descriptor */
const struct {
    char bLength;               // bLength         - Descriptor size in bytes (12h)
    char bDescriptorType;       // bDescriptorType - The constant DEVICE (01h)
    unsigned int bcdUSB;        // bcdUSB          - USB specification release number (BCD)
    char bDeviceClass;          // bDeviceClass    - Class Code
    char bDeviceSubClass;       // bDeviceSubClass - Subclass code
    char bDeviceProtocol;       // bDeviceProtocol - Protocol code
    char bMaxPacketSize0;       // bMaxPacketSize0 - Maximum packet size for endpoint 0
    unsigned int idVendor;      // idVendor        - Vendor ID
    unsigned int idProduct;     // idProduct       - Product ID
    unsigned int bcdDevice;     // bcdDevice       - Device release number (BCD)
    char iManufacturer;         // iManufacturer   - Index of string descriptor for the manufacturer
    char iProduct;              // iProduct        - Index of string descriptor for the product.
    char iSerialNumber;         // iSerialNumber   - Index of string descriptor for the serial number.
    char bNumConfigurations;    // bNumConfigurations - Number of possible configurations
} device_dsc = {
      0x12,                   // bLength
      0x01,                   // bDescriptorType
      0x0200,                 // bcdUSB
      0x00,                   // bDeviceClass
      0x00,                   // bDeviceSubClass
      0x00,                   // bDeviceProtocol
      8,                      // bMaxPacketSize0
      USB_VENDOR_ID,          // idVendor
      USB_PRODUCT_ID,         // idProduct
      0x0001,                 // bcdDevice
      0x01,                   // iManufacturer
      0x02,                   // iProduct
      0x03,                   // iSerialNumber
      0x01                    // bNumConfigurations
  };

/* Configuration 1 Descriptor */
const char configDescriptor1[]= {
    // Configuration Descriptor
    0x09,                   // bLength             - Descriptor size in bytes
    0x02,                   // bDescriptorType     - The constant CONFIGURATION (02h)
    0x29,0x00,              // wTotalLength        - The number of bytes in the configuration descriptor and all of its subordinate descriptors
    1,                      // bNumInterfaces      - Number of interfaces in the configuration
    1,                      // bConfigurationValue - Identifier for Set Configuration and Get Configuration requests
    0,                      // iConfiguration      - Index of string descriptor for the configuration
    USB_SELF_POWER,         // bmAttributes        - Self/bus power and remote wakeup settings
    USB_MAX_POWER,          // bMaxPower           - Bus power required in units of 2 mA

    // Interface Descriptor
    0x09,                   // bLength - Descriptor size in bytes (09h)
    0x04,                   // bDescriptorType - The constant Interface (04h)
    0,                      // bInterfaceNumber - Number identifying this interface
    0,                      // bAlternateSetting - A number that identifies a descriptor with alternate settings for this bInterfaceNumber.
    2,                      // bNumEndpoint - Number of endpoints supported not counting endpoint zero
    0x03,                   // bInterfaceClass - Class code
    0,                      // bInterfaceSubclass - Subclass code
    0,                      // bInterfaceProtocol - Protocol code
    0,                      // iInterface - Interface string index

    // HID Class-Specific Descriptor
    0x09,                   // bLength - Descriptor size in bytes.
    0x21,                   // bDescriptorType - This descriptor's type: 21h to indicate the HID class.
    0x01,0x01,              // bcdHID - HID specification release number (BCD).
    0x00,                   // bCountryCode - Numeric expression identifying the country for localized hardware (BCD) or 00h.
    1,                      // bNumDescriptors - Number of subordinate report and physical descriptors.
    0x22,                   // bDescriptorType - The type of a class-specific descriptor that follows
    USB_HID_RPT_SIZE,0x00,  // wDescriptorLength - Total length of the descriptor identified above.

    // Endpoint Descriptor
    0x07,                   // bLength - Descriptor size in bytes (07h)
    0x05,                   // bDescriptorType - The constant Endpoint (05h)
    USB_HID_EP | 0x80,      // bEndpointAddress - Endpoint number and direction
    USB_TRANSFER_TYPE,      // bmAttributes - Transfer type and supplementary information
    0x40,0x00,              // wMaxPacketSize - Maximum packet size supported
    EP_IN_INTERVAL,         // bInterval - Service interval or NAK rate

    // Endpoint Descriptor
    0x07,                   // bLength - Descriptor size in bytes (07h)
    0x05,                   // bDescriptorType - The constant Endpoint (05h)
    USB_HID_EP,             // bEndpointAddress - Endpoint number and direction
    USB_TRANSFER_TYPE,      // bmAttributes - Transfer type and supplementary information
    0x40,0x00,              // wMaxPacketSize - Maximum packet size supported
    EP_OUT_INTERVAL         // bInterval - Service interval or NAK rate
};

const struct 
{
  char report[USB_HID_RPT_SIZE];
}

hid_rpt_desc =
  {
     {0x06, 0x00, 0xFF,       // Usage Page = 0xFF00 (Vendor Defined Page 1)
      0x09, 0x01,             // Usage (Vendor Usage 1)
      0xA1, 0x01,             // Collection (Application)
      0x85, 0x01,             // Report ID=1 (This is a global variable)
      0x15, 0x00,             // Logical Minimum (data bytes in the report may have minimum value = 0. This is a global variable)
      0x26, 0xFF, 0x00,       // Logical Maximum (data bytes in the report may have maximum value = 256. This is a global variable)

  // Input report(ID=1)
      0x19, 0x01,             // Usage Minimum
      0x29, 0xFF,             // Usage Maximum
      0x75, 0x08,             // Report Size: 8-bit field size
      0x95, 0x3F,             // Report Count (63 + 1 byte for the report ID)
      0x81, 0x02,             // Input (Data, Var, Abs)

  // Output report(ID=1)
      0x19, 0x01,             // Usage Minimum
      0x29, 0xFF,             // Usage Maximum
      0x75, 0x08,             // Report Size: 8-bit field size
      0x95, 0x3F,             // Report Count (63 + 1 byte for the report ID)
      0x91, 0x02,             // Output (Data, Var, Abs)
      
      
      0x85, 0x02,             // Report ID=1 (This is a global variable)
      
      // Input report(ID=2)
      0x19, 0x01,             // Usage Minimum
      0x29, 0x08,             // Usage Maximum
      0x75, 0x08,             // Report Size: 8-bit field size
      0x95, 0x01,             // Report Count (1 byte + 1 byte for the report ID)
      0x81, 0x02,             // Input (Data, Var, Abs)
      
      // Output report(ID=2)
      0x19, 0x01,             // Usage Minimum
      0x29, 0x08,             // Usage Maximum
      0x75, 0x08,             // Report Size: 8-bit field size
      0x95, 0x01,             // Report Count (1 byte + 1 byte for the report ID)
      0x91, 0x02,             // Output (Data, Var, Abs)

      0xC0},                   // End Collection
  };

//Language code string descriptor
const struct {
  char bLength;
  char bDscType;
  unsigned int string[1];
  } strd1 = {
      4,
      0x03,
      {0x0409}
    };


//Manufacturer string descriptor
const struct{
  char bLength;
  char bDscType;
  unsigned int string[10];
  }strd2={
    22,           //size of this descriptor string
    0x03,
    {'p','a','u','l','f','j','u','j','o',' '}
  };

//Product string descriptor
const struct{
  char bLength;
  char bDscType;
  unsigned int string[10];
}strd3={
    22,          //size of this descriptor string
    0x03,
    {'P','I','C','1','8','F','2','5','5','0'}
 };
 //Serial Number descriptor
const struct{
  char bLength;
  char bDscType;
  unsigned int string[6];
}strd4 = {
    14,          //size of this descriptor string
    0x03,
    {'A','B','C','1','2','3'} // Count as two bytes
 };

//Array of configuration descriptors
const char* USB_config_dsc_ptr[1];
//Array of string descriptors
const char* USB_string_dsc_ptr[3];



const code char mesg0[]="MikroC Pro V6.50    ";
const code char mesg1[]="HID Terminal USB PC ";
const code char * Messages[]={mesg0,mesg1};

unsigned char TEXTE[64];
unsigned char * txt;
unsigned char  addr;
char * PtR;
char * PtE;
char cnt;
char kk;
unsigned int  i,j,k;
char CRam1[20];
unsigned int EAH,EAL,EA0;
float ff1;
int FDC_Mini;  // issu du potar de recopie      ADC value <20
int FDC_Maxi;   // issu du potar de recopie    ADC value > 1000
int Etat;
volatile unsigned int Count1;
volatile int Flag_Timer1;
unsigned char sec;
unsigned int Toggle;


void USB_Init_Desc();
void strConstRamCpy(unsigned char *dest, const code char *source) ;

void interrupt(){
   USB_Interrupt_Proc();                  // USB servicing is done inside the interrupt
}

void Interrupts() iv 0x0018 ics ICS_AUTO
{
   // ------  timer 1  ----------------
  if  ( (TMR1IE_bit==1) && ( TMR1IF_bit==1))
   {  // Test "Peripheral Interrupt Request Register 1" for Timer1 Flag

     Count1++;
     if (Count1>=Nb_Count1)
       {
        Count1=0;
        Flag_Timer1=1;
        TMR1IE_bit=0;
      }
      // 24 * 41.666mS = 1 seconde et init timer1 à 3035  et prescaler=1/8  at 48MHz
      TMR1H= 0x0B; // Hi (3035);
      TMR1L= 0xDB; // Lo (3035);
      PIR1.TMR1IF=0;
   }
}



void USB_Init_Desc(){
  USB_config_dsc_ptr[0] = &configDescriptor1;
  USB_string_dsc_ptr[0] = (const char*)&strd1;
  USB_string_dsc_ptr[1] = (const char*)&strd2;
  USB_string_dsc_ptr[2] = (const char*)&strd3;
  USB_string_dsc_ptr[3] = (const char*)&strd4;
  }


void Init_Timer1(void)
 {
  T1CON=0;
  T1CKPS1_bit=1;  //prescal select=11 => 1/8
  T1CKPS0_bit=1;
 // T1GCON=0;
  TMR1H= 0x0B; // Hi (3035);     // 41mS at 49MHZ
  TMR1L= 0xDB; // Lo (3035);
 // TMR1H= NbCycles_T1>>8;
 // TMR1L= NbCycles_T1 & 0x00FF;
   Count1=0;
  Flag_Timer1=0;
  PIR1.TMR1IF=0;     // Reset Timer1 Flag
  PIE1.TMR1IE=0;  //Disable interrupt TMR1
  IPR1.TMR1IP=0;  // disable High level interrupt
  INTCON.PEIE=0;  // disable peripheral interrupt
  TMR1ON_bit=0;   // timer1 OFF
}

void Float2Ascii (float x, unsigned char *str,char precision)
{
 /* converts a floating point number to an ascii string */
 /* x is stored into str, which should be at least 30 chars long */
 int ie, i, k, ndig;
 double y;
 ndig = ( precision<=0) ? 7 : (precision > 22 ? 23 : precision+1);
 ie = 0;
 /* if x negative, write minus and reverse */
 if ( x < 0)
 {
   *str++ = '-';
   x = -x;
 }
 /* put x in range 1 <= x < 10 */
 if (x > 0.0) while (x < 1.0)
 {
   x *= 10.0;                // a la place de =*
   ie--;
 }
 while (x >= 10.0)
 {
   x = x/10.0;
   ie++;
 }
 // in f format, number of digits is related to size
 ndig += ie;                                // a la place de =+
 //round. x is between 1 and 10 and ndig will be printed to
 // right of decimal point so rounding is ...
 for (y = i = 1; i < ndig; i++)
 y = y/10.;
 x += y/2.;
 if (x >= 10.0) {x = 1.0; ie++;}
 if (ie<0)
 {
   *str++ = '0'; *str++ = '.';
   if (ndig < 0) ie = ie-ndig;
   for (i = -1; i > ie; i--)  *str++ = '0';
 }
 for (i=0; i < ndig; i++)
 {
   k = x;
   *str++ = k + '0';
   if (i ==  ie ) *str++ = '.';
   x -= (y=k);
   x *= 10.0;
  }
 *str = '\0';
}

void Init_ADC()
{
   ADCON0 = 0x00;// select channel 0 (AN0)
   ADCON1 = 0;
   ADCON2 = 0;
   ADCON1.VCFG1=0;    // VREF- = VSS=0V
   ADCON1.VCFG0=0;  // VREF+ = VDD=+5V
   ADCON1.PCFG3=1;
   ADCON1.PCFG2=1;
   ADCON1.PCFG1=1;
   ADCON1.PCFG0=0;
   ADCON0.ADON = 1;//Enable A/D module
   //ADCON2 setup: Right justified, Tacq=16Tad, Tad=2*Tosc (or Fosc/2)
   ADCON2.ADFM=1; // right justified
   ADCON2.ACQT2=1;  // 111 => 20 Tad
   ADCON2.ACQT1=1;
   ADCON2.ACQT0=1;
   ADCON2.ADCS2=1;  // FOSC /64
   ADCON2.ADCS1=1;
   ADCON2.ADCS0=1;
}

void Read_ADC0()
{
    ADCON0.CHS0=0; // Channel 0 (AN0) Position du potar rectiligne
    Delay_ms(1);
    ADCON0.GO_DONE = 1;//Start A/D Conversion
    while(ADCON0.GO_DONE ==1);//Loop here until A/D conversion completes
    EA0=(ADRESH <<8) + ADRESL;
 }
 

// --- Copie le texte depuis ROM vers RAM
void strConstRamCpy(unsigned char *dest, const code char *source) {
  while (*source)*dest++ = *source++ ;
  *dest = 0 ;    // terminateur
}



void main(void)
{
  PORTA=0;
  TRISA0_bit=1;  // Ana input  EA0
  TRISA1_bit=0;  // output to led verte (cablée  sur la carte StartUSB )
  TRISB0_bit=1;   // must be configure as input for I2C
  TRISB1_bit=1;    // must be configure as input for I2C
  TRISB3_bit=0;   // output to led rouge externe
  CMCON = 0x07;   // Disable comparators

  Delay_ms(150);    // wait for a while to oscillator stabilizes

  LED_Sup=0;
  LED_Inf=0;
  Toggle=0;

  Init_ADC();     // select channel 0 (AN0)
   Delay_ms(100);
   txt=&TEXTE[0];
  
  
  HID_Enable(&readbuff,&writebuff);       // Enable HID communication
  

  Init_Timer1();
  Flag_Timer1=0;
  TMR1IE_bit=1;
  TMR1ON_bit=1;
  PEIE_bit=1;
  GIE_bit=1;
  sprintf( &writebuff," Timer1 initialisé et Armé \r\n");
  // rajout test timer1 pour ne pas etre bloqué
  // si on a pas activé le terminal HID :  USB HID Libray
  while((Flag_Timer1==0)&& (!HID_Write(&writebuff,64)) );


   while(1)
  {
    while(!HID_Read() && (Flag_Timer1==0));                  // wait for data on USB
   if(Flag_Timer1==1)
   {
    Flag_Timer1=0;
    Count1=0;
    TMR1IE_bit=1;
    Read_ADC0();  // result into EA0
    ff1=(float)EA0 * 5.00 /1024.0;
    Float2Ascii (ff1, CRam1,2);
    if (Toggle==1)
      {
        Read_ADC0();  // result into EA0
        ff1=(float)EA0 * 5.00 /1024.0;
        Float2Ascii (ff1, CRam1,2);
        sprintf( &writebuff," ADC=% 5u    %04X  soit %s Volts \r\n",EA0,EA0,CRam1);
        while(!HID_Write(&writebuff,64));
      }
    }
   else
   {
        if(strncmp(&readbuff,"RED_ON",6)==0 )  LED_Sup=1;
        if(strncmp(&readbuff,"RED_OFF",7)==0 )  LED_Sup=0;
        if(strncmp(&readbuff,"GREEN_ON",8)==0) LED_Inf=1;
        if(strncmp(&readbuff,"GREEN_OFF",9)==0) LED_Inf=0;
        if(strncmp(&readbuff,"TOGGLE",6)==0) Toggle= Toggle ^ 0x0001;
       if (strncmp(&readbuff,"ADC",3)==0)
       {

          Read_ADC0();  // result into EA0
          ff1=(float)EA0 * 5.00 /1024.0;
          Float2Ascii (ff1, CRam1,2);
          sprintf( &writebuff," ADC=% 5u    %04X  soit %s Volts \r\n",EA0,EA0,CRam1);
        }
      while(!HID_Write(&writebuff,64));
    }
    if (EA0 >800)
    {
       LED_Sup=1;
     }
     if (EA0 <100)
     {
        LED_Inf=1;
      }
    Delay_ms(500);
  }
}
 

Actually I have PIC18F2550 in house and PIC programmer. For learning purpose I would like to start working with that. The aim is to get throughput of 50 kilo sample per second with a string of 10 characters on USB full speed. Otherwise the string size can be reduced to 5 characters.

How about PIC USB Starter Kit with PIC32 ? Would it be easy to implement the application on starter kit compared to PIC18F2550 ?

I guess MPLAB' MLA (PIC8 and PIC16) and MPLAB Harmony (PIC32) both have demo projects for USB protocol, right ?

How about the host software on PC side ?
 
Last edited:

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top