View previous topic :: View next topic |
Author |
Message |
krolikbest
Joined: 02 Jan 2017 Posts: 118

|
Posted: Mon Jul 14, 2025 12:54 pm Post subject: Need some hint to usb device development |
|
|
Hi,
I plan to use nRF24 device along with my Windows machine. This device will play as a receiver and it should work with few of transmitters (also nRF24l01) by multiplexing channels. (theoretically do-able). Now I have to solve how connect nRF24 to Windows machine and there it comes idea of use some chip/device with 32U on board for example.. The software (I plan to build) on Windows could communicate with this 32U chip/device and allow to config some properties on it or collects infos from it.So basically saying, nRF24 is connected with 32U device via SPI and 32U is connected to PC via USB. Now question - device 32U should be discovered by Windows machine as a some device with own HID, not as a COMXX, what do I need to use to achive it? Next question - concerning my own software, is there any library that Bascom provides I could use in my application, and in case Yes, any examples how do I consume such library?
Thanks,
Martin
[b][color=red](BASCOM-AVR version : 2.0.8.5 , Latest : 2.0.8.7 )[/b][/color] |
|
Back to top |
|
 |
albertsm
Joined: 09 Apr 2004 Posts: 6203 Location: Holland

|
Posted: Mon Jul 14, 2025 1:28 pm Post subject: |
|
|
The MCS Shop has an USB add on.
It is suited for the chip you use.
Here is one of the samples :
It will only work with the add on. But you can see how HID works.
Code: |
'------------------------------------------------------------------------------
' (c) 1995-2025 MCS Electronics
' hid_generic-M32u4.bas
' generic HID input and output sample, based on Atmels sample
'------------------------------------------------------------------------------
$regfile = "m32u4def.dat"
$crystal = 16000000
$baud = 19200
$hwstack = 64
$swstack = 64
$framesize = 64
Const Mdbg = 1 ' if you want to see all USB communication turn it on but turin it off(0) for your application since it will cost space
Const Chiddevice = 1 ' set this on for HID devices
Config Clockdiv = 1 ' we let the internal clock divider divide by 1 which will result in 8 Mhz clock
Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Const Vendor_id = &H16D0 ' MCS Vendor ID
Const Product_id = &H201D ' MCS product ID, you can buy a PID in the MCS shop
'specific device constants
Const Ep_control_length = 32
Const User_conf_size = 41
Const Size_of_report = 53
Const Device_class = 0
Const Device_sub_class = 0
Const Device_protocol = 0
Const Release_number = &H1000
Const Length_of_report_in = 8
Const Length_of_report_out = 8
Const Interface_nb = 0
Const Alternate = 0
Const Nb_endpoint = 2
Const Interface_class = 3 ' HID
Const Interface_sub_class = 0
Const Interface_protocol = 0
Const Interface_index = 0
'Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Print "USB GENERIC test"
Declare Sub Usb_user_endpoint_init
Declare Sub Hid_test_hit ()
Declare Sub Hid_task ()
Declare Sub Hid_task_init ()
Const Usb_config_attributes_reserved = &H80
Const Usb_config_buspowered = Usb_config_attributes_reserved
Const Usb_config_selfpowered = Usb_config_attributes_reserved Or &H40
Const Usb_config_remotewakeup = Usb_config_attributes_reserved Or &H20
Const Nb_interface = 1
Const Conf_nb = 1
Const Conf_index = 0
Const Usb_remote_wakeup = 0
Const Conf_attributes = Usb_config_buspowered + Usb_config_remotewakeup
Const Max_power = 50 ' 100 mA
Const Interface_nb_mouse = 0
Const Alternate_mouse = 0
Const Nb_endpoint_mouse = 1
Const Interface_class_mouse = 3 ' HID Class
Const Interface_sub_class_mouse = 1 ' Sub Class is Mouse
Const Interface_protocol_mouse = 2 ' Mouse
Const Interface_index_mouse = 0
Const Nb_endpoints = 2 ' number of endpoints in the application including control endpoint
Const Ep_kbd_in = 1 ' Number of the mouse interrupt IN endpoint
Const Ep_hid_in = 1
Const Ep_hid_out = 2
Const Endpoint_nb_1 = Ep_hid_in Or &H80
Const Ep_attributes_1 = 3 ' BULK = 0x02, INTERUPT = 0x03
Const Ep_in_length_1 = 8
Const Ep_size_1 = Ep_in_length_1
Const Ep_interval_1 = 20 ' Interrupt polling interval from host
Const Endpoint_nb_2 = Ep_hid_out
Const Ep_attributes_2 = 3 ' BULK = 0x02, INTERUPT = 0x03
Const Ep_out_length = 8
Const Ep_size_2 = Ep_out_length
Const Ep_interval_2 = 20 ' interrupt polling from host
Config Usb = Device , Language = &H0409 , Manufact = "MCS" , Product = "MCSHID162" , Serial = "MC0001"
'Dim some user vars
Dim Usb_kbd_state As Byte , Usb_key As Byte , Usb_data_to_send As Byte
Dim Dummy As Byte , Dummy1 As Byte , Dummy2 As Byte
Print "task init"
Usb_task_init ' init the usb task
Hid_task_init ' init the USB task
Do
Usb_task 'call this subroutine once in a while
Hid_task 'call this subroutine once in a while
'you can call your sub program here
Loop
'nothing needed to init
Sub Hid_task_init ()
'nothing
End Sub
'HID task must be checked regular
Sub Hid_task ()
If Usb_connected = 1 Then ' Check USB HID is enumerated
Usb_select_endpoint Ep_hid_out ' Get Data Repport From Host
If Ueintx.rxouti = 1 Then ' Is_usb_receive_out())
Dummy1 = Uedatx : Print "Got : " ; Dummy1 ' it is important that you read the same amount of bytes here as were sent by the host !
Dummy2 = Uedatx : Print "Got : " ; Dummy2
Dummy = Uedatx : Print "Got : " ; Dummy
Dummy = Uedatx : Print "Got : " ; Dummy
Dummy = Uedatx : Print "Got : " ; Dummy
Dummy = Uedatx : Print "Got : " ; Dummy
Dummy = Uedatx : Print "Got : " ; Dummy
Dummy = Uedatx : Print "Got : " ; Dummy
Usb_ack_receive_out
End If
If Dummy1 = &H55 And Dummy2 = &HAA Then ' Check if we received DFU mode command from host
Usb_detach ' Detach Actual Generic Hid Application
Waitms 500
'Goto &H1FC00 'goto bootloader
'here you could call the bootloader then
End If
Usb_select_endpoint Ep_hid_in ' Ready to send these information to the host application
If Ueintx.txini = 1 Then ' Is_usb_in_ready())
Uedatx = 1
Uedatx = 2
Uedatx = 3
Uedatx = 4
Uedatx = 5
Uedatx = 6
Uedatx = 7
Uedatx = 8
Usb_ack_fifocon ' Send data over the USB
End If
End If
End Sub
'this function is called for user requests
Function Usb_user_read_request (type As Byte , Request As Byte) As Byte
#if Mdbg
Print "USB_USER_READ_REQ"
#endif
Usb_string_type = Uedatx 'Usb_read_byte();
Usb_descriptor_type = Uedatx 'Usb_read_byte();
Usb_user_read_request = 0
Select Case Request
Case Get_descriptor :
Select Case Usb_descriptor_type
Case Report : Call Hid_get_report ()
Usb_user_read_request = 1
Case Hid : Call Hid_get_hid_descriptor ()
Usb_user_read_request = 1
Case Else
Usb_user_read_request = 0
End Select
Case Set_configuration :
Select Case Usb_descriptor_type
Case Set_report : Call Hid_set_report ()
Usb_user_read_request = 1
Case Else
Usb_user_read_request = 0
End Select
Case Get_interface :
'// usb_hid_set_idle();
Call Usb_hid_get_interface ()
Usb_user_read_request = 1
Case Else
Usb_user_read_request = 0
End Select
End Function
'usb_init_device.
'This function initializes the USB device controller and
'configures the Default Control Endpoint.
Sub Usb_init_device ()
#if Usbhost
Usb_select_device
#endif
#if _chip = 70 Or _chip = 71 'if usb1287 or usb646
If Usbsta.id = 1 Then 'is it an USB device?
#endif
Uenum = Ep_control ' select USB endpoint
If Ueconx.epen = 0 Then ' usb endpoint not enabled yet
Call Usb_configure_endpoint (ep_control , Type_control , Direction_out , Size_32 , One_bank , Nyet_disabled )
End If
#if _chip = 70 Or _chip = 71 'if usb1287 or usb646
End If
#endif
End Sub
'init the user endpoints
Sub Usb_user_endpoint_init (byval Nm As Byte)
Call Usb_configure_endpoint (ep_hid_in , Type_interrupt , Direction_in , Size_8 , One_bank , Nyet_enabled )
Call Usb_configure_endpoint (ep_hid_out , Type_interrupt , Direction_out , Size_8 , One_bank , Nyet_enabled )
End Sub
'the following data is all USB data
Usb_dev_desc :
Data 18 , Device_descriptor ' size and device_descriptor
Data 0 , 2 ' Usb_write_word_enum_struc(USB_SPECIFICATION)
Data Device_class , Device_sub_class ' DEVICE_CLASS and DEVICE_SUB_CLASS
Data Device_protocol , Ep_control_length ' device protol and ep_control_length
Data Vendor_id % ' Usb_write_word_enum_struc(VENDOR_ID)
Data Product_id % ' Usb_write_word_enum_struc(PRODUCT_ID)
Data Release_number % ' Usb_write_word_enum_struc(RELEASE_NUMBER)
Data Man_index , Prod_index ' MAN_INDEX and PROD_INDEX
Data Sn_index , Nb_configuration ' SN_INDEX and NB_CONFIGURATION
Usb_conf_desc :
Data 9 , Configuration_descriptor ' length , CONFIGURATION descriptor
Data User_conf_size % ' total length of data returned
Data Nb_interface , Conf_nb ' number of interfaces for this conf. , value for SetConfiguration resquest
Data Conf_index , Conf_attributes ' index of string descriptor , Configuration characteristics
Data Max_power ' maximum power consumption
Data 9 , Interface_descriptor ' length , INTERFACE descriptor type
Data Interface_nb , Alternate ' Number of interface , value to select alternate setting
Data Nb_endpoint , Interface_class ' Number of EP except EP 0 ,Class code assigned by the USB
Data Interface_sub_class , Interface_protocol ' Sub-class code assigned by the USB , Protocol code assigned by the USB
Data Interface_index ' Index Of String Descriptor
Data 9 , Hid_descriptor ' length , HID descriptor type
Data Hid_bdc % , 8 ' Binay Coded Decimal Spec. release , Hid_country_code
Data Hid_class_desc_nb , Hid_descriptor_type ' Number of HID class descriptors to follow , Report descriptor type
Data Size_of_report % ' HID KEYBOARD LENGTH
Data 7 , Endpoint_descriptor ' Size Of This Descriptor In Bytes , ENDPOINT descriptor type
Data Endpoint_nb_1 , Ep_attributes_1 ' Address of the endpoint ,Endpoint's attributes
Data Ep_size_1 % ' Maximum packet size for this EP , Interval for polling EP in ms
Data Ep_interval_1
Data 7 , Endpoint_descriptor ' Size Of This Descriptor In Bytes , ENDPOINT descriptor type
Data Endpoint_nb_2 , Ep_attributes_2 ' Address of the endpoint , Endpoint's attributes
Data Ep_size_2 % ' Maximum packet size for this EP
Data Ep_interval_2 ' Interval for polling EP in ms
Usb_hid_report :
Data &H06 , &HFF , &HFF ' 04|2 , Usage Page (vendordefined?)
Data &H09 , &H01 ' 08|1 , Usage (vendordefined
Data &HA1 , &H01 ' A0|1 , Collection (Application)
' // IN report
Data &H09 , &H02 ' 08|1 , Usage (vendordefined)
Data &H09 , &H03 ' 08|1 , Usage (vendordefined)
Data &H15 , &H00 ' 14|1 , Logical Minimum(0 for signed byte?)
Data &H26 , &HFF , &H00 ' 24|1 , Logical Maximum(255 for signed byte?)
Data &H75 , &H08 ' 74|1 , Report Size( = field size in bits = 1 byte
Data &H95 , Length_of_report_in ' 94|1:ReportCount(size) = repeat count of previous item
Data &H81 , &H02 ' 80|1: IN report (Data,Variable, Absolute)
' // OUT report
Data &H09 , &H04 ' 08|1 , Usage (vendordefined)
Data &H09 , &H05 ' 08|1 , Usage (vendordefined)
Data &H15 , &H00 ' 14|1 , Logical Minimum(0 for signed byte?)
Data &H26 , &HFF , &H00 ' 24|1 , Logical Maximum(255 for signed byte?)
Data &H75 , &H08 ' 74|1 , Report Size( = field size in bits = 1 byte
Data &H95 , Length_of_report_out ' 94|1:ReportCount(size) = repeat count of previous item
Data &H91 , &H02 ' 90|1: OUT report (Data,Variable, Absolute)
' // Feature report
Data &H09 , &H06 ' 08|1 , Usage (vendordefined)
Data &H09 , &H07 ' 08|1 , Usage (vendordefined)
Data &H15 , &H00 ' 14|1 , LogicalMinimum(0 for signed byte)
Data &H26 , &HFF , &H00 ' 24|1 , Logical Maximum(255 for signed byte)
Data &H75 , &H08 ' 74|1 , Report Size( =field size in bits = 1 byte
Data &H95 , &H04 ' 94|1:ReportCount
Data &HB1 , &H02 ' B0|1: Feature report
Data &HC0 ' C0|0 , End Collection
|
_________________ Mark |
|
Back to top |
|
 |
JC
Joined: 15 Dec 2007 Posts: 630 Location: Cleveland, OH

|
Posted: Mon Jul 14, 2025 7:28 pm Post subject: |
|
|
There are many ways to solve most projects.
The approach you mentioned is a very reasonable one.
You did not mention if this is a large scale, commercial product, with lots of devices, or if you are only building one system at the moment.
If I was going to do this, I might try what I think would be a simpler approach.
(I think there is a significant learning curve to using embedded USB)
I would take a $2 (USD), (i.e. very cheap!), Nano and plug its USB port into the PC. It will show up under Device Manager as a serial port. Then I’d write the Windows program using whatever language (C, Visual Basic, Python, etc.), that you want to use.
The data through put for a serial device exceeds that for a HID device, and the serial communications mode is also pre-embedded into Windows, so no special Windows driver is needed for either.
The Nano would interface to one of the nRF24 devices, as the Master, controlled by the PC.
You could have the PC broadcast packets to all of the remote nRF24 devices. Use a “packet”, with a Start of Packet character, Command Byte, Data, and a CheckSum byte. The remote that is being asked for data can then reply, with its data packet, (including its I.D.).
With this configuration you do not have to learn about using an embedded USB module, you have a faster data rate, you have a very low cost, and the software on the Nano is very minimal, (easy). It simply passes PC commands to the nRF, and passes the received data back to the PC. Adding ISR driven buffers is easy with Bascom. Having a Start of Packet character and a CheckSum makes it easy for the Nano to recognize good data, and pass that to the PC.
(With RF, there is always “noise”, and garbage data, etc., that the system has to recognize and ignore.).
Just my thoughts…
Good luck with your project!
JC |
|
Back to top |
|
 |
albertsm
Joined: 09 Apr 2004 Posts: 6203 Location: Holland

|
Posted: Mon Jul 14, 2025 8:01 pm Post subject: |
|
|
The example sends and receives 8 bytes. but it can be more like 32 or 64 with some simple mods.
The advantage is that you do not need any driver and it works on all devices like PC, android, IOS , linux
The USB stack does need time from the micro so when your app must do a lot of other stuff then it might not be practicle.
I built USB LCD displays, and many other USB HID devices. But every application has it own demands. _________________ Mark |
|
Back to top |
|
 |
krolikbest
Joined: 02 Jan 2017 Posts: 118

|
Posted: Tue Jul 15, 2025 8:49 am Post subject: |
|
|
Hi,
this solution you (@JC) write about is the most convenient, I have solved tasks this way several times. I am considering using USB chip because of the lack of need to configure the COMXX port in my potential application (unless I am wrong). In other words, the application is supposed to automatically detect the 32U device and send/receive data to/from the 32U device.Regarding the amount of transmitters, no more as 7-8. The whole installation is so far for test and it will create a grid of sensors collecting data from a specific area of up to 400 m2 at most. WiFi is out, interference, need for a router, etc.
Assuming I go for a USB HID device, how should my application (I will be writing in FreePascal) communicate with the HID device? Are there any examples, e.g. in Visual Basic or another language, showing how to establish communication with the HID device; do I need, on the side of e.g. Visual basics, some special library to communicate with this device? Or am I, not yet familiar with the subject, already complicating the issue for myself?
Regards,
Martin |
|
Back to top |
|
 |
albertsm
Joined: 09 Apr 2004 Posts: 6203 Location: Holland

|
Posted: Tue Jul 15, 2025 9:04 am Post subject: |
|
|
when you google for freepascal and hid component you find lot of code. it is probably not much different than the ones i use with delphi.
usb hid can detect any plugged device. it will not the VID and PID and a serial etc. just look at the sample i shown and config usb.
it also detects when you remove it. i give all my devices a unique PID so i know which device is plugged.
when you need to transpost lots of data the CDC (com is a better alternative). while USB can also do high speed it also means less time for your other code.
USB does require that you put some time in learning it. the samples i made are translated from the atmel C code. but it is nothing to be afraid of for an experienced bascom programmer.
It is more like taking the sample and adjusting things and adding your own code. _________________ Mark |
|
Back to top |
|
 |
krolikbest
Joined: 02 Jan 2017 Posts: 118

|
Posted: Tue Jul 15, 2025 9:38 am Post subject: |
|
|
So, putting informations in order for myself, the code in Bascom will enable OS to detect the device (that's obvious), on the side of my application I need to find a solution to communicate my application with the detected device. All clear.
Regards,
Martin |
|
Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|