This is Google's cache of http://odroid.foros-phpbb.com/t2421-using-the-hardkernel-usb-io-board-under-python. It is a snapshot of the page as it appeared on 17 Feb 2013 08:13:25 GMT. The current page could have changed in the meantime. Learn more
Tip: To quickly find your search term on this page, press Ctrl+F or ⌘-F (Mac) and use the find bar.

Text-only version
 
Using the Hardkernel USB IO board under python

Log in

I forgot my password

HardKernel

Latest topics

Poll

How is your Over Clocking(ODROID-X)?
25% 25% [ 9 ]
33% 33% [ 12 ]
42% 42% [ 15 ]

Total Votes : 36

Using the Hardkernel USB IO board under python 5 5 1

    Using the Hardkernel USB IO board under python

    Share

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Sat Jan 26, 2013 5:10 am

    Update:
    The source to the HK USB IO board demo ROM is now hosted on Git
    The python module I created to access the ROM is also available on Git.
    Project: https://github.com/hardkernel/Odroid-USBIO

    This is a short howto on controlling the IO board sold by HK under python from the odroid-x2

    (1) first remove any old python-usb package (we will use the pyusb-1 package)
    $ sudo apt-get remove python-usb

    (2) download and install pyusb-1 http://sourceforge.net/projects/pyusb/files/PyUSB%201.0/
    $ tar -xvf pyusb-1.0.0a3.tar.gz
    $ cd pyusb-1.0.0a3
    $ sudo python setup.py install

    (3) Follow the USB IO instructions on the IO board wiki for how to load the usbdemo hex file to the IO board

    (4) attach your USB IO board to the odroid-x2

    (5) run the following python program
    Code:

    #!/usr/bin/python
    import usb.core
    import usb.util
    import sys
    import time

    # find our device
    dev = usb.core.find(idVendor=0x04d8, idProduct=0x003f)
    # was it found
    if dev is None:
            raise ValueError('Device not found')

    # handle if device is busy
    if dev.is_kernel_driver_active(0) is True:
      dev.detach_kernel_driver(0)

    # set the active configuration.  No args the first config
    # will become the active one
    dev.set_configuration()

    # toggle LED by sending toggle_led command
    print "Toggling LED"
    dev.write(1, [0x80], 0, 100)
    time.sleep(1)
    dev.write(1, [0x80], 0, 100)

    # reading switch status
    print "Reading switch status  1=not pressed,  0=pressed"
    dev.write(1, [0x81], 0, 100)
    ret = dev.read(0x81, 64, 0, 100)
    print ret[1]

    dev.reset()


    This program will toggle the LED's and read the status of the pushbutton on the USB IO board
    Note: The USB IO board demo hex file has a loop that you can replace with your own code, look in their main.c


    Last edited by mlinuxguy on Fri Feb 15, 2013 8:18 am; edited 1 time in total

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Sat Jan 26, 2013 7:04 pm

    Customizing the HK USB IO board demo program

    Project name: USB Device - HID - Simple Custom Demo
    File: main.c
    Function: ProcessIO()

    USB commands switch statement in the IO board ROM
    Code:
    case 0x80:  //Toggle LEDs command
    case 0x81:  //Get push button state
    case 0x37:   //Read POT command.

    Replace or add your USB command to this switch statement in the ProcessIO() function

    Example: case 0x82: // read a GPIO pin
    Implement your code in main.c, and use 0x82 in python to read the GPIO pin state

    Function: ProcessIO()
    Code:
          switch(ReceivedDataBuffer[0])            //Look at the data the host sent, to see what kind of application specific command it sent.
            {
                case 0x80:  //Toggle LEDs command
                  blinkStatusValid = FALSE;         //Stop blinking the LEDs automatically, going to manually control them now.
                    if(mGetLED_1() == mGetLED_2())
                    {
                        mLED_1_Toggle();
                        mLED_2_Toggle();
                    }
                    else
                    {
                        if(mGetLED_1())
                        {
                            mLED_2_On();
                        }
                        else
                        {
                            mLED_2_Off();
                        }
                    }
                    break;
                case 0x81:  //Get push button state
                    //Check to make sure the endpoint/buffer is free before we modify the contents
                    if(!HIDTxHandleBusy(USBInHandle))
                    {
                        ToSendDataBuffer[0] = 0x81;            //Echo back to the host PC the command we are fulfilling in the first byte.  In this case, the Get Pushbutton State command.
                    if(sw3 == 1)                     //pushbutton not pressed, pull up resistor on circuit board is pulling the PORT pin high
                    {
                       ToSendDataBuffer[1] = 0x01;         
                    }
                    else                           //sw3 must be == 0, pushbutton is pressed and overpowering the pull up resistor
                    {
                       ToSendDataBuffer[1] = 0x00;
                    }
                    //Prepare the USB module to send the data packet to the host
                        USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&ToSendDataBuffer[0],64);
                    }
                    break;

                case 0x37:   //Read POT command.  Uses ADC to measure an analog voltage on one of the ANxx I/O pins, and returns the result to the host
                    {
                        WORD_VAL w;
                       
                        //Check to make sure the endpoint/buffer is free before we modify the contents
                       if(!HIDTxHandleBusy(USBInHandle))
                       {
                           w = ReadPOT();               //Use ADC to read the I/O pin voltage.  See the relevant HardwareProfile - xxxxx.h file for the I/O pin that it will measure.
                                              //Some demo boards, like the PIC18F87J50 FS USB Plug-In Module board, do not have a potentiometer (when used stand alone).
                                              //This function call will still measure the analog voltage on the I/O pin however.  To make the demo more interesting, it
                                              //is suggested that an external adjustable analog voltage should be applied to this pin.
                      ToSendDataBuffer[0] = 0x37;     //Echo back to the host the command we are fulfilling in the first byte.  In this case, the Read POT (analog voltage) command.
                      ToSendDataBuffer[1] = w.v[0];     //Measured analog voltage LSB
                      ToSendDataBuffer[2] = w.v[1];     //Measured analog voltage MSB

                            //Prepare the USB module to send the data packet to the host
                           USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&ToSendDataBuffer[0],64);
                       }               
                    }
                    break;
            }


    odroid
    Member of HardKernel
    Member of HardKernel

    Languages ​​spoken: English, Korean
    Devices: ODROID-Q, ODROID-X
    Posts: 3117
    Join date: 2010-05-12
    Location: Seoul, Korea

    Re: Using the Hardkernel USB IO board under python

    Post by odroid on Sun Jan 27, 2013 3:44 am

    Thank you for this great tutorial.

    When we have time after releasing of 3D enabled Ubuntu, I want to make a SPI-like dot-matrix LED control project with USB IO board.

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Thu Feb 07, 2013 8:37 pm

    A proposal for a generic HK USB IO board rom

    Concept: Modify the usbdemo code for the USB IO board to provide some generic I/O functionality

    Implementation:
    Modify the USBDEMO switch statement to add the following:
    (1) generic GPIO IN/OUT via 0x82=in and 0x83=out
    (2) SPI read and write via 0x84 and 0x85
    (3) I2C read and write via 0x86 and 0x87
    (4) ADC conversion via 0x88
    (5) PWM out via 0x89
    (6) UART in and out, 0x8a and 0x8b

    Benefits:
    The PIC18F docs and sample code have a fairly steep learning curve, let alone the challenge of getting the programming environment setup properly.
    By extending the PIC demo code to include some basic functionality such as GPIO pin I/O, the utilization of the HK USB IO board would be much easier for a broader audience.

    First pass implementation
    Generic GPIO implementation seems the easiest to start with

    Notes: I'm a bit snowed under with other Linux projects currently but did manage to get the PIC programming env setup under linux. Getting the env properly setup to find all include files was the hardest part.

    odroid
    Member of HardKernel
    Member of HardKernel

    Languages ​​spoken: English, Korean
    Devices: ODROID-Q, ODROID-X
    Posts: 3117
    Join date: 2010-05-12
    Location: Seoul, Korea

    Re: Using the Hardkernel USB IO board under python

    Post by odroid on Fri Feb 08, 2013 6:15 am

    Good idea...

    We may try to make some commands to read/write the SFRs of PIC MCU first.

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Fri Feb 08, 2013 8:25 am

    Can you check my logic here?

    In the simple demo program I have added the following test code to main.c:
    Code:

    subroutine:  UserInit()
    //HK_GPIO_RD4
        TRISDbits.TRISD4=1;      //HK set for input RD4
        TRISDbits.TRISD5=0;      //HK set for output RD5
    #define rd4in  PORTDbits.RD4
    #define rd5out  PORTDbits.RD5

    subroutine:  ProcessIO()
     case 0x82:  // get input value on RD4
                    if (!HIDTxHandleBusy(USBInHandle))
                    {
                        ToSendDataBuffer[0] = 0x82; // echo cmd
                        if (rd4in == 1) { ToSendDataBuffer[1] = 0x01;}
                        else            { ToSendDataBuffer[1] = 0;}
                        ToSendDataBuffer[2] = 0;    // msb
                        //Prepare the USB module to send the data packet to the host
                   USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&ToSendDataBuffer[0],64);
                    }
                    break;
                case 0x83:  // ouptut a value on RD5
                    // code to be added
                    break;

    I will add the code to output on RD5 once I figure out how to extract the value I want to set from the USB packet

    If this test of 0x82 and 0x83 functionality works I can modify it easily enough to pass the GPIO pin to use and direction to set.
    Right now just trying to make sure I have the code correct.

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Sat Feb 09, 2013 12:12 am

    The sample PIC code I showed above works
    The code 0x82 is sent via python to the HK USB IO board, it returns the state of pin RD4
    (which was set to GPIO input)

    I get a 0 or a 1 depending on if the pin RD4 is tied to ground or VCC
    This python code added to the earlier post reads the RD4 value:
    Code:

    # custom 0x82 code for reading RD4 as GPIO input
    print "Reading RD4 input status"
    dev.write(1, [0x82], 0, 100)
    ret = dev.read(0x81, 64, 0, 100)
    print ret[1]


    Now I need to get output working on RD5
    After that go back and change the PIC code accept:
    PIC_PIN# and IO_direction

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Sat Feb 09, 2013 3:46 am

    I have both GPIO in and out working now (RD4=in, and RD5=out)

    PIC code for RD5=out
    Code:

    case 0x83:  // ouptut a value on RD5
      if (ReceivedDataBuffer[1] == 1) { LATDbits.LATD5 = 1;}
      else
      if (ReceivedDataBuffer[1] == 0) { LATDbits.LATD5 = 0;}
      break;


    python code for RD5=out (odroid-x2 side)
    Code:

    # output using 0x83 a 1 or 0 on RD5
    print "Output value on RD5, 1 for 5 sec then 0 for 5, repeat"
    dev.write(1, [0x83,1], 0, 100)
    time.sleep(5)
    dev.write(1, [0x83,0], 0, 100)
    time.sleep(5)
    dev.write(1, [0x83,1], 0, 100)
    time.sleep(5)
    dev.write(1, [0x83,0], 0, 100)


    Next up is coding for generic GPIO pin assignment
    I was leaning toward designating:
    RD4, RD5, RD6, and RD7
    as generic GPIO pins that can be assigned as input or output on the fly via python

    This would leave me SPI, DAC, ANLG IN, and others still free to later support

    Notes:
    I have attached a hex file for programming the HK USB IO board
    This version 0.1 implements the default demo (switch and led) and my use of
    RD4 and RD5 for GPIO pins.

    Use this program under windows to flash the hex file into the USB IO board:
    "C:\Users\someone\Downloads\Microchip_Solutions_v2012-10-15\USB\Device - Bootloaders\HID\HIDBootloader (Windows).exe"
    (note: hold the switch in while plugging USB IO board into your PC)

    PIC env notes:
    (1) You must use the C18 compiler since the newer compiler fails to support the USB lib
    (2) Linux and the C18 compiler do not get along very well (use windows IDE)
    (3) You must specify INCLUDE dirs in the project file or it fails to find includes
    (4) Using the c18 libraries This is quite possible but requires that you use the windows batch file in the ~\src directory to rebuild the old c18 libraries for mplabx (do this as administrator)
    Attachments
    usbio_v0_1.zip
    USB IO board hex file version 0.1 (implements just RD4=in, RD5=out)
    You don't have permission to download attachments.
    (7 Kb) Downloaded 0 times


    Last edited by mlinuxguy on Wed Feb 13, 2013 5:01 pm; edited 1 time in total

    odroid
    Member of HardKernel
    Member of HardKernel

    Languages ​​spoken: English, Korean
    Devices: ODROID-Q, ODROID-X
    Posts: 3117
    Join date: 2010-05-12
    Location: Seoul, Korea

    Re: Using the Hardkernel USB IO board under python

    Post by odroid on Sat Feb 09, 2013 5:29 am

    Great progress!

    I'm thinking about this protocol. Please review it and get back to me.

    Get Register
    The identifier GETREG (0x98) retrieves value of a microcontroller register. Byte 1 specifies the register as detailed in appendix I. The response is the same as the command, except the register value is given in byte 2.
    Directly accessing registers requires in-depth knowledge of the base microcontroller, but it provides greater flexibility that the other commands. Refer to the base microcontroller data sheet for details.
    Example:
    98 CC 00 00 Command – Get TMR2 register
    98 CC 5A 00 Response – Value is 0x5A

    Set Register
    The identifier SETREG (0x99) sets the value of a microcontroller register. Byte 1 specifies the register as detailed in appendix I. Byte 2 specifies the new value. The response is the same as the command.
    Example:
    99 CC 5A 00 Command – Set TMR2 reg to 0x5A
    99 CC 05 00 Response – Value set

    Get Register Bit
    The identifier GETBIT (0x9A) retrieves a single bit from a microcontroller register. Byte 1 indicates the register as detailed in appendix I and byte 2 indicates the bit (0-7).
    In the response, byte 3 is 0 for clear and 1 for set.
    Example:
    9A F0 06 00 Command – Get INTCON3 bit 6
    9A F0 06 01 Response – Value is 0x01

    Set Register Bit
    The identifier SETBIT (0x9B) sets or clears a single bit of a microcontroller register. Byte 1 indicates the register as detailed in appendix I and byte 2 indicates the bit (0-7).
    Byte 3 is 0 for clear and 1 for set. The response is the same as the command.
    9B F0 06 01 Command – Set INTCON3 bit 6 to 1
    9B F0 06 01 Response – Bit set

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Sat Feb 09, 2013 7:19 pm

    First pass response

    Where is Appendix I?
    http://ww1.microchip.com/downloads/en/DeviceDoc/30684A.pdf
    (only goes to Appendix B)

    Good
    (1) Excellent low level control
    (2) Flexible programming of PIC18
    (3) Full access to PIC registers
    (4) higher-level code wrappers around these low-level functions easily layered on later

    Bad
    (1) Detailed knowledge of PIC18F45K50 programming required
    (2) No definition of bulk transfer protocol (ex: DAC waveform transfer, or SPI data block return)

    Dual-rom strategy
    Implement two PIC18 ROM types:
    - your flexible PIC18 ROM - (target: advanced users)
    - high-level rom encapsulating fixed functionality (target: general user)

    The high-level rom would define something like the following:
    Fixed pins for GPIO
    Fixed pins for PWM
    Fixed pins for I2C or SPI
    Fixed pins for Analog in and DAC
    (This would cover everyone just wanting basic I/O)

    The Flexible ROM features:
    Initial feature set allowing control of PIC18 registers
    Defines: Data transfer in/out
    Later features build libraries around low-level register access, thus encapsulating advanced features without as much low-level knowledge

    Both ROM's can be released in stages with more features added later releases

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Sat Feb 09, 2013 9:22 pm

    Implementation of 4 GPIO pins complete
    I have configured the PIC demo code for general GPIO use on pins:
    RD4, RD5, RD6, and RD7

    The default is RD4-RD5=input, and RD6-RD7=output
    You can reprogram them from the defaults (change direction of the GPIO pin)

    The version of the PIC hex code is now: 0.2
    (flash it to the HK USB IO card)

    Example python code
    Code:

    #!/usr/bin/python
    import usb.core
    import usb.util
    import sys
    import time

    class gpio:
            rd4 = 1
            rd5 = 2
            rd6 = 3
            rd7 = 4
            dir_output = 0
            dir_input  = 1

    # find our device
    dev = usb.core.find(idVendor=0x04d8, idProduct=0x003f)
    # was it found
    if dev is None:
            raise ValueError('Device not found')

    # handle if device is busy
    if dev.is_kernel_driver_active(0) is True:
      dev.detach_kernel_driver(0)

    # set the active configuration.  No args the first config
    # will become the active one
    dev.set_configuration()

    # toggle LED by sending toggle_led command
    print "Toggling LED"
    dev.write(1, [0x80], 0, 100)
    time.sleep(1)
    dev.write(1, [0x80], 0, 100)

    # default is: rd4,rd5=input and rd6,rd7=output
    print "output 1 for 5 sec on RD7, then back to 0"
    dev.write(1, [0x83, gpio.rd7, 1], 0, 100)
    time.sleep(5)
    dev.write(1, [0x83, gpio.rd7, 0], 0, 100)

    print "program RD6 for input"
    dev.write(1,[0x84, gpio.rd6, gpio.dir_input], 0, 100)
    print "read rd6 value"
    dev.write(1,[0x82, gpio.rd6], 0, 100)
    ret = dev.read(0x81, 64, 0, 100)
    print ret[1]

    dev.reset()

    Attachments
    usbio_v0_2.zip
    USB IO board hex file version 0.2 (implements GPIO on rd4, rd5, rd6, and rd7)
    You don't have permission to download attachments.
    (7 Kb) Downloaded 0 times

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Sat Feb 09, 2013 11:23 pm

    ADC input on RA0 working
    I left the demo code in place for reading a POT output and implemented python code to read the value (the HK board does not have a POT on RA0)

    Notes:
    - 10-bit ADC so expected values range 0-1023
    - Reference is VDD, which in my case is 3.29 volts
    - my voltage divider reads 1.63 volts in the middle


    Put following code at end of previous python example (just before the final dev.reset)
    Code:
    # read ADC value on RA0
    print "Do ADC conversion on pin RA0"
    dev.write(1,[0x37], 0, 100)
    ret = dev.read(0x81, 64, 0, 100)
    value = ret[2] << 8
    value = value | ret[1]
    print value


    Sample run with RA0 at VDD reference:
    Do ADC conversion on pin RA0
    1023

    Sample run with RA0 in middle of voltage divider at 1.63 volts
    Do ADC conversion on pin RA0
    517

    Notes: The v0.2 PIC ROM file from above implements RA0 ADC input

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Sun Feb 10, 2013 6:50 am

    Version 0.3 HK USB IO demo-ROM now features
    (1) ADC input on pins RA0 and RA1 (select which channel to do the ADC conversion)
    (2) GPIO pins on RD4, RD5, RD6, and RD7
    (3) added command to return USB IO board rom version

    Python example code for ROM version and ADC on RA1
    note: add this to the existing python demo program
    Code:
    # read ROM version
    print "Read PIC ROM version"
    ver = ''
    dev.write(1, [0x85], 0, 100)
    ret = dev.read(0x81, 64, 0, 100)
    ver += chr(ret[1]) + '.'
    ver += chr(ret[2])
    print ver

    # read ADC value on RA1
    print "Do ADC conversion on pin RA1"
    dev.write(1,[0x38], 0, 100)
    ret = dev.read(0x81, 64, 0, 100)
    value = ret[2] << 8
    value = value | ret[1]
    print value

    dev.reset()


    hex command notes:
    0x37 = ADC RA0
    0x38 = ADC RA1
    0x80 = toggle LED
    0x81 = read switch state
    0x82 = read GPIO pin#
    0x83 = output on GPIO pin#
    0x84 = configure GPIO direction
    0x85 = return ROM version

    Sample output
    $ ./pyusbio.py
    Read PIC ROM version
    0.3
    Do ADC conversion on pin RA1
    506
    Attachments
    usbio_v0_3.zip
    USB IO board hex file version 0.3 (4 GPIO and 2 channels of ADC)
    You don't have permission to download attachments.
    (8 Kb) Downloaded 0 times

    odroid
    Member of HardKernel
    Member of HardKernel

    Languages ​​spoken: English, Korean
    Devices: ODROID-Q, ODROID-X
    Posts: 3117
    Join date: 2010-05-12
    Location: Seoul, Korea

    Re: Using the Hardkernel USB IO board under python

    Post by odroid on Mon Feb 11, 2013 9:09 am

    mlinuxguy wrote:
    Where is Appendix I?
    http://ww1.microchip.com/downloads/en/DeviceDoc/30684A.pdf
    (only goes to Appendix B)


    Sorry. It was my fault.
    The SFRs are described in page 89~92 of the datasheet.

    I agree that SPI/I2C/UART should have a separated API to get the maximum throughput.
    Let me think about the more efficient packet handling.

    sert00
    Member
    Member

    Languages ​​spoken: english,italian
    Devices: odroid-U2
    Posts: 20
    Join date: 2013-01-30

    Re: Using the Hardkernel USB IO board under python

    Post by sert00 on Mon Feb 11, 2013 2:24 pm

    my god guys,thanks for this great tutorial!i'm awaiting my u2 yet,but already playing a bit with gpio on raspberry e gertboard...can i use this tutorial on my u2 as well?(i ordered the io expansion)

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Mon Feb 11, 2013 4:45 pm

    sert00 wrote:can i use this tutorial on my u2 as well?(i ordered the io expansion)
    You can use the HK USB IO board with any compute device that can send/receive the needed commands over USB with the IO board. Including the U2.
    Note: I've been testing my demo rom with both the Odroid-x2, an Ubuntu x86_64 PC, and an RPI

    Python use
    Though I have been using Python to drive the HK USB IO board, any language on the USB host side that can send USB packets could be used (Java, Perl, C, etc.. the language should have a USB library to make it easy to use)


    Last edited by mlinuxguy on Tue Feb 12, 2013 1:05 am; edited 1 time in total

    sert00
    Member
    Member

    Languages ​​spoken: english,italian
    Devices: odroid-U2
    Posts: 20
    Join date: 2013-01-30

    Re: Using the Hardkernel USB IO board under python

    Post by sert00 on Mon Feb 11, 2013 5:02 pm

    ok,thanks man!i haven't any skills on languages,i begin learning python in my freetime only some days ago..choosed python due to the easy rather than c\c++ etc

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Mon Feb 11, 2013 6:36 pm

    Update: Turns out the value for 9600 baud is 77
    That means the FOSC value is: 48mhz and the USB lower clock rate is not set
    equation: 48M / (64*9600) = spbrg+1 = 78.125, so spbrg = 77

    ------ left previous question for reference ------
    Note: It turned out the reason for the garbage when I tested 77 as the value
    was due to a pointer bug on my part

    Question:
    What is the HK USB IO board FOSC setting when it is configured to do USB?
    48mhz or 16mhz?

    I'm struggling to get the UART on the HK USB IO board to talk at 9600baud
    The issue appears to be that I do not know for sure how to compute the baud rate settings since I am not sure what oscillator clock the USB IO board is running at.

    Documents state: 48mhz
    However I find this in the code:
    Code:
            #if(USB_SPEED_OPTION == USB_FULL_SPEED)
                OSCTUNE = 0x80; //3X PLL ratio mode selected
                OSCCON = 0x70;  //Switch to 16MHz HFINTOSC

    I have tried various combinations of 48mhz or 16mhz for the FOSC setting in the equation to calculate baud rate, however I keep getting garbage on the 9600 baud LCD I have connected (no o-scope in-house).
    Code:

    Open1USART( USART_TX_INT_OFF &
        USART_RX_INT_OFF &
        USART_ASYNCH_MODE &
        USART_EIGHT_BIT &
        USART_CONT_RX &
        USART_BRGH_LOW,
        25 );  // 48M /(16*9600) = spbrg+1 = 312.5, so spbrg = 312
                // 48M /(64*9600) = spbrg+1 = 78.125, so spbrg = 77
    // SPBRG = (Fosc / (16 x Baud rate)) - 1, BRGH = 1 High Speed
    // SPBRG = (Fosc / (64 x Baud rate)) - 1, BRGH = 0 Low Speed
    // note due to USB this code appears to happen, OSCCON = 0x70;  //Switch to 16MHz HFINTOSC
    // if 16mhz then 16mhz / (64 * 9600) -1 = 26 - 1

    I've tried 312, 77, and 25 to no avail


    Last edited by mlinuxguy on Wed Feb 13, 2013 8:38 pm; edited 1 time in total

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Tue Feb 12, 2013 12:31 am

    Version 0.31 demo ROM update
    This version enables the UART (TX and RX pins on HK USB IO board)

    Communication protocol
    case 0x86: // send char string out UART
    case 0x87: // test if UART has char available to read
    case 0x88: // read a single char from UART
    case 0x89: // send a single char to UART

    Rom version update
    The rom version now reports: Major.minor.fix (3 digits returned)

    Example python code writing text to a Serial enabled LCD display
    note: At some point I will clean up the python code and put it in a easy to use python class
    Code:

    # output a string to LCD
    print "send string to LCD"
    dev.write(1, [0x86,0xfe,0x01,0], 0, 100)  # clear the LCD screen
    dev.write(1, [0x86,0xfe,0x0d,0], 0, 100)  # blinking block cursor
    dev.write(1, [0x86,0x34,0x32,0x20,ord('H'),ord('e'),ord('l'),ord('l'),ord('o'),0], 0, 100)
    dev.write(1, [0x86,0xfe,192,0], 0, 100)  # move down a row
    dev.write(1, [0x86,ord('P'),ord('I'),ord('C'),ord('1'),ord('8'),0], 0, 100)

    This code prints on the LCD:
    42 Hello
    PIC18

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Wed Feb 13, 2013 7:00 am

    I have converted my python code for controlling my HK USB IO board rom to a module

    Sample output:
    $ ./hk_usb_io.py
    0.31
    False
    1
    517
    no

    Python code using the new module
    Its much easier to use and extend in this form
    Code:

    usb = init()                    # init the USB IO board

    print rom_version(usb)          # print rom version

    toggle_led(usb)                # toggle the LED

    a = read_switch(usb)            # read the switch status
    print a

    gpio_init(usb,rd7,dir_input)    # configure gpio RD7 as input
    a = gpio_in(usb,rd7)            # read the GPIO pin RD7
    print a

    a = adc_ra1(usb)                # do ADC conversion on pin RA1
    print a

    # LCD on serial port (UART IO to a serial attached LCD)
    ser_putc(usb,chr(0xfe))        # clear LCD screen
    ser_putc(usb,chr(0x01))
    ser_putc(usb,chr(0xfe))        # block cursor
    ser_putc(usb,chr(0x0d))
    ser_puts(usb,"Hello World")
    ser_puts(usb,chr(0xfe) + chr(192))      # move to next line
    ser_puts(usb,"From Odroid-x2")

    if (ser_test(usb)):            # check if incoming char on UART
            a = ser_getc(usb)
            print a
    else:
            print "no"

    close(usb)                      # reset USB device


    The Python module
    Code:

    #!/usr/bin/python
    import usb.core
    import usb.util
    from array import array
    import sys
    import time

    u_ad0 = 0x37    # read ADC value from RA0
    u_ad1 = 0x38    # read ADC value from RA1
    u_rom = 0x85    # get PIC rom version
    u_led = 0x80    # toggle LED
    u_swc = 0x81    # get switch pressed or not
    u_gpd = 0x84    # configure GPIO direction on a pin
    u_gpi = 0x82    # read value on GPIO pin
    u_gpo = 0x83    # write value to GPIO pin
    u_uss = 0x86    # send a string to the UART
    u_tst = 0x87    # test if UART has a char available
    u_urc = 0x88    # read a single char from UART
    u_usc = 0x89    # send a single char to the UART
    rd4 = 1
    rd5 = 2
    rd6 = 3
    rd7 = 4
    dir_output = 0
    dir_input  = 1
    def init():                                                    # setup USB device structure
            # find our device
            dev = usb.core.find(idVendor=0x04d8, idProduct=0x003f)
            # was it found
            if dev is None:
                    raise ValueError('Device not found')
            # handle if device is busy
            if dev.is_kernel_driver_active(0) is True:
                    detach_kernel_driver(0)
            # set the active configuration.  No args the first config
            # will become the active one
            dev.set_configuration()
            return dev
    def rom_version(dev):                          # get PIC ROM version
            # read ROM version
            dev.write(1, [u_rom], 0, 100)
            ret = dev.read(0x81, 64, 0, 100)
            rom_version = ''
            rom_version += chr(ret[1])
            rom_version += '.'
            rom_version += chr(ret[2])
            rom_version += chr(ret[3])
            return rom_version
    def toggle_led(dev):                            # toggle LED
            dev.write(1, [u_led], 0, 100)
    def read_switch(dev):                          # read switch press
            dev.write(1, [u_swc], 0, 100)
            sw = dev.read(0x81, 64, 0, 100)
            if (sw[1] == 0):
                    return True
            else:
                    return False
    def gpio_init(dev,pin,pdir):            # set GPIO direction on pin
            dev.write(1,[u_gpd, pin, pdir], 0, 100)
    def gpio_out(dev,pin):                          # otuput a value on GPIO pin
            dev.write(1, [u_gpo, pin, 1], 0, 100)
    def gpio_in(dev,pin):                          # read value on GPIO pin
            dev.write(1,[u_gpi, pin], 0, 100)
            ret = dev.read(0x81, 64, 0, 100)
            return ret[1]
    def adc_ra0(dev):                                      # do ADC conversion on RA0
            dev.write(1,[u_ad0], 0, 100)
            ret = dev.read(0x81, 64, 0, 100)
            value = ret[2] << 8
            value = value | ret[1]
            return value
    def adc_ra1(dev):                                      # do ADC conversion on RA0
            dev.write(1,[u_ad1], 0, 100)
            ret = dev.read(0x81, 64, 0, 100)
            value = ret[2] << 8
            value = value | ret[1]
            return value
    def ser_test(dev):                                      # check if a char available on serial port
            dev.write(1, [u_tst], 0, 100)
            ret = dev.read(0x81, 64, 0, 100)
            return ret[1]
    def ser_putc(dev,schar):                        # send a char to the serial port
            a = map( ord, schar)
            a.insert(0, u_usc)
            dev.write(1, a, 0, 100)
    def ser_puts(dev, strval):                      # send a string to the serial port
            a = map( ord, strval)
            a.insert(0, u_uss)
            a.append(0)
            dev.write(1, a, 0, 100)
    def ser_getc(dev):                                      # get a single char from the serial port
            dev.write(1, [u_urc], 0, 100)
            ret = dev.read(0x81, 64, 0, 100)
            return ret[1]
    def close(dev):                                        # reset USB device
            dev.reset()

    odroid
    Member of HardKernel
    Member of HardKernel

    Languages ​​spoken: English, Korean
    Devices: ODROID-Q, ODROID-X
    Posts: 3117
    Join date: 2010-05-12
    Location: Seoul, Korea

    Re: Using the Hardkernel USB IO board under python

    Post by odroid on Wed Feb 13, 2013 9:57 am

    We are implementing the low level access of all the SFRs now.
    We will upload the source code of firmware in our git-hub by this weekend.

    Please reserve the commands of 0x98,0x99,0x9a and 0x9b. Wink

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Thu Feb 14, 2013 5:59 am

    Trying to configure RC1 for PWM output
    My attempt at getting RC1 doing independent PWM output copied your ' ie_pwm(void) '
    routine but instead of independently controlling RC1 when I change the duty cycle for RC1 your LED dims instead of mine.

    quote from PIC PDF
    In Single Output mode, PWM steering allows any of the
    PWM pins to be the modulated signal. Additionally, the
    same PWM signal can be simultaneously available on
    multiple pins.


    I don't want to hack up too much of your LED control until I understand this better. I thought I could output independent PWM signals without messing with your LED control. Perhaps no one is setting the 'Output mode' to single?

    Any thoughts on my modification of your LED control?
    Code:
    // setup PWM output for pin RC1
    void pwm_rc1(int duty) {
          ANSELC &= 0xFB;
          TRISC  |= 0x02; //- RC1 input
          //- PWM Period = [PR2 + 1] * 4 * TOSC * TMR2 Prescale Value
          //- 3,750 Hz  = (199 + 1) * 4 * 1/48,000,000 * 16
          PR2 = 199;
          CCP1CON = 0x0C; //- PWM mode
          //- Duty Cycle Ratio = CCPR1L:CCP1CON<5:4> / 4 * (PR2 + 1)
          //- 50 %  =        400          * 1/48,000,000 * 16
          // CCPR1L = 0x64; //- 50%
                    CCPR1L = duty; //- 50%
          //- CCPR1L = 0x0;
          T2CON |= 0x06;
          TRISC  &= 0xF9; //- RC1 output, RC2 leave as output
    }

    Now trying PWM output on RB4
    Looks like I'll have to spend more time digging through the documentation. I moved to RB4 but not getting any output.
    Code:

    void pwm_rc1(int duty) {
       //ANSELB &= 0xFB;
            ANSELBbits.ANSB4=0;
       //TRISB  |= 0x10; //- RB4 input
            TRISBbits.TRISB4=1;
            PSTR1CON = 0x02;
       //- PWM Period = [PR2 + 1] * 4 * TOSC * TMR2 Prescale Value
       //- 3,750 Hz  = (199 + 1) * 4 * 1/48,000,000 * 16
       PR2 = 199;
       CCP1CON = 0x0C; //- PWM mode
       //- Duty Cycle Ratio = CCPR1L:CCP1CON<5:4> / 4 * (PR2 + 1)
       //- 50 %  =        400          * 1/48,000,000 * 16
       // CCPR1L = 0x64; //- 50%
            CCPR1L = duty; //- 50%
       //- CCPR1L = 0x0;
       T2CON |= 0x06;
       //TRISC  &= 0xF9; //- RC1 output, RC2 leave as output
            //TRISB  &= 0xEF; //- RB4 output
            TRISBbits.TRISB4=0;
    }

    odroid
    Member of HardKernel
    Member of HardKernel

    Languages ​​spoken: English, Korean
    Devices: ODROID-Q, ODROID-X
    Posts: 3117
    Join date: 2010-05-12
    Location: Seoul, Korea

    Re: Using the Hardkernel USB IO board under python

    Post by odroid on Thu Feb 14, 2013 12:29 pm

    We have added the SFR read/write command and released the source code via github.
    https://github.com/hardkernel/Odroid-USBIO

    Please merge your ADC,UART,PWM and some other commands when you have time..

    recliq
    Member
    Member

    Languages ​​spoken: English, German
    Devices: ODROID-U2
    Posts: 29
    Join date: 2013-01-22
    Location: Germany

    Re: Using the Hardkernel USB IO board under python

    Post by recliq on Thu Feb 14, 2013 1:55 pm

    This is really great news!

    I want to use my io-board for some simple SPI project and allthough I have some little experience in C/C++ I found the default firmware didn't support SPI...

    I had a look at the PIC dox and I had to admit that writing a firmware for the PIC is way over my head :/

    Now that I found this thread I gained hope again!

    Please keep up the excellent work!

    mlinuxguy
    Advanced User
    Advanced User

    Devices: ODROID-X
    Posts: 284
    Join date: 2012-08-11

    Re: Using the Hardkernel USB IO board under python

    Post by mlinuxguy on Thu Feb 14, 2013 5:21 pm

    Issues with merging
    I started using the c18 libraries to easily add UART support to my ROM and was looking in those libraries for PWM output.
    Note: needed c18 compiler anyway since USB support in X8 doesn't work yet

    To use the libraries with MPLAB X IDE, it was a simple matter of running the supplied windows batch file as ADMIN, giving it the 18f45k50 string to build, and copying the 2 libraries created to my project directory.

    The old libraries rebuilt to work with MPLABX are: p18f45k50.lib and p18f45k50_e.lib

    Issue: If I merge my code into yours the UART (and soon PWM) section will require you have those libraries available to build the project.
    They are freely available to download, just need rebuilt for MPLABX

    Question: Did you switch to the c18 compiler to get USB to work on the PIC?
    It will not work properly under the default x8 compiler

    Options:
    (1) I merge all my code in and users download the c18 compiler and rebuild those 2 libs for the mplabx IDE.
    (2) I strip out the UART code so the libraries are not needed (and stop working on PWM)
    (3) I move the UART routines into the project and cut out need to link to the c18 libs. Repeat for PWM and others used.

    What are your thoughts?
    Note: I made the first commit today of my changes. I left in the use of the c18 PIC library as I use the UART code and soon the PWM code.


    Last edited by mlinuxguy on Fri Feb 15, 2013 1:00 am; edited 1 time in total

      Current date/time is Sun Feb 17, 2013 9:13 am