Tuesday, August 16, 2016

CC1101 Atmega32u USB dongle

The goal

Create first "thing" on USB, also make use of CC1101.

Usability

Big, basically it's interfacing CC1101 through USB using LUFA, also CC1101 module is detachable so I can use this dongle to something else using SPI + two GPIO (RX/TX + INT) pins.

Parts

All resistor/condensators/les are smd 0805 type.
  • 1 x CC1101 module
  • 1 x atmega32u4
  • 2 x 22 ohm
  • 1 x 850 ohm
  • 2 x 10k
  • 3 x 100n
  • 1 x 1u
  • 1 x 100u
  • 2 x 15p
  • 1 x 8Mhz crystal
  • 1 x USB connector
  • 1 x led (red or green)
  • 1 x 3965 3.3v regulator
  • 2 x tactile switch
  • 1 x 2 pin socket 1.27 mm
  • 1 x 6 pin socket 1.27 mm

Code


Hardware

  • 1 x CC1101 wireless ISM radio module

Description


I always wanted to build something on USB, whatever it would be ;) and recently was wondering to buy CC1111 EMK dongle or YARD Stick One which are awesome, specially the second. Finally I've ended with CC1101 which has no USB support (CC1111 has additional MCU inside), and needs to be interfaced through SPI bus and some GPIO pins.

Then was the question how to play with it? It had 1.27 pin raster which I've never worked before and whole module was small enough begging to make USB dongle out of it. I've started to search the net for something similar, to look how to start, then I found busware's CC1101 USB Litle module V3, which it's brilliant in it's simplicity. I'm a Linux Slackware user for years (with some small breaks), and KISS (keep it simple stupid) philosophy fits me very well, so I build my own CC1101 usb dongle based on theirs USB Litle module V3. Probably if I found it before I would just buy it, but all fun with making PCB would miss me.

First USB dongles!

Atmega32u4 supports USB, so it's quite simple to make firmware together with LUFA.

CC1101 module is detachable

Thanks to decision to add 1.27mm pin sockets instead of soldering directly, I can use this dongle to something else in the future, I have whole SPI bus with SS + 2 GPIO witch are also RX/TX and can do full interrupts.

Up view, hot glue was necessary

They are not so fat at all

Probably something smaller than atmega32u4 would be sufficient, but hey, maybe someday I would need some more flash? Also making it compatible with busware's enables me to use my software with theirs hardware, some day.

Back side with atmega32u4

Electric scheme


Nothing interesting here, just SPI connection, some pins etc. Connections are based on busware's dongle additionally I added reset button for atmega.

CC1101 atmega32u dongle circuit

There board was redesigned couple of times, finally I ended with size below, which fits 3 usb ports in my laptop [1,2,3]. So you can put two dongles on the sides [1, 3] and one usb cable between them [2]. I think it's quite nice size optimization, it was 1.5 x larger at the beginning.

CC1101 Atmega32u dongle PCB

PCB


Board was made using my custom PCB laminator, now making double-sided boards is a pleasure!. On picture below, you can find top side on which Atmega32u4 will be placed. Board is already drilled, for such small holes I recommend you to use some driller stand, I use home made. On single side board drilling from hand is sufficient, but when comes to double-side, you can easily drill mistakenly with a small angle and end with no precision on the other side.

Top of the PCB with drilled holes

Previously I was connecting one side to another with part of very thin wire, but when comes to connection under microcontroller, it needs to be very flat, and using wire always caused problems with mcu positioning during soldering.

I've seen on the net that there are special rivets for this type of connection, but I started to search something that I have in one of my desk drawer. I never throw out wires cut off from resistors/capacitors/diodes, often I use them to make connections, but on the same side of the board.

I use rest of resitor/condensator/diode wires

Wires have different thickness and "feel", I use more flexible ones to this. Can't tell from which component they where cut off.

The wire needs to fit exactly into the hole, it means that you need to use some pressure to put it there, but not too much. It just need to be stable in the hole. After putting the wire, it needs to be cut even from each side, you need to decide how much, I can't really measure this.

The PCBs I use for small double-sided boards is thicker, thanks to this connections between each side are more stable, it's harder to bend the board.

The wire length should be equal on each of the pcb side

And now, super-ultimate tool for finishing the process - alligator wrench. It's perfect for small PCBs, and it can deliver exact amount of pressure thanks to good lever.

Super magic tool for rivets!

Below you can find photo after finishing connections with alligator wrench, as you can see they look pretty well and I cut wires (two picture above) to exact length. When you cut too much, the wire won't be flatten enough to make good connection, when you make wire too long, it could spill on other routes. Also using to hard wire is bad, because it will have problems with flattening, and for sure will damage the hole.

Front with rivets

Now only check connections with digital multimeter, add a soldering mask with solder, and it should work.

Back with rivets

Firmware


I used LUFA framework to emulate virtual serial port on Linux side, and if you look into the CC1101 Atmega32u C LUFA source code it's quite easy using one of LUFA's examples.

Dongle acts as a bridge: serial port -> air and back, so everything that you write to serial will be send over air, it's quite transparent. But of course there was a problem with configuration, how to send CC1101 config to the module? With help came DTR signal, which can be triggered from PC. LUFA's code will see it not as serial data but more like a control command. The problem solved itself, now after sending DTR CC1101 config is send over regular serial and transmitting 0xFF means the end.
uint8_t usb_cfg = 0;
void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t *const CDCInterfaceInfo) {
   L(EIMSK, INT2);
 usb_cfg = (CDCInterfaceInfo->State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR) != 0;
}

Two dongles at the same time


As you can see on the first picture, I've build two dongles, one has red other green led, now how to distinguish between them from Linux side? I've changed USB's ProductID constant and add additional configuration to udev, now I can talk with my dongles using /dev/cc1101_green and /dev/cc1101_red link, instead of thinking which serial port number it acquired.
const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = {
 .Header                 = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},

 .USBSpecification       = VERSION_BCD(1,1,0),
 .Class                  = CDC_CSCP_CDCClass,
 .SubClass               = CDC_CSCP_NoSpecificSubclass,
 .Protocol               = CDC_CSCP_NoSpecificProtocol,

 .Endpoint0Size          = FIXED_CONTROL_ENDPOINT_SIZE,

 .VendorID               = 0x03EB,
 .ProductID              = 0x2045,   // change here
 .ReleaseNumber          = VERSION_BCD(0,0,1),

 .ManufacturerStrIndex   = STRING_ID_Manufacturer,
 .ProductStrIndex        = STRING_ID_Product,
 .SerialNumStrIndex      = USE_INTERNAL_SERIAL,

 .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
};
Define additional links using udev:
SUBSYSTEM=="tty", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2044", SYMLINK+="cc1101_green"
SUBSYSTEM=="tty", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2045", SYMLINK+="cc1101_red"

7 comments:

  1. Hi... i look at this and think its great.. but would it be possible to use a arduino nano ?? ... by means of serial over usb ?

    ReplyDelete
    Replies
    1. Hey, Thanks! I think it should be possible. Basically I do the same, but in my case I have "virtual" serial (as CDC) on atmega32u4. You will have slightly slower speed at other end (PC/laptop), and maybe you would need to synchronize cc1101 packet speed with arudiono nano serial settings, but in general it should work.

      Delete
  2. hi thanks for your reaction..i will have a look at it but i think at this point its a little to hard for me.. i am not realy into communication over usb and software on the OS site...
    I think you make a very nice project but use of pcb en at32u is a step to far for most people... i found this project looking for a alternative for the yard stick one .. i would encourage you to try with arduino nano or soo ..... gtz from holland


    OOH and yess its a great chip :)

    ReplyDelete
    Replies
    1. Yep, it's a great chip. I also couldn't find rfCat alternative so I've started to build one :).

      If I'll find some more time I'll port this to arduino nano, this should not be a problem.

      You could think about arduino leonardo, it also has atmega32u with usb, so this code shold be working in theory.

      Delete
  3. Thank you for your advise... maybe i will try do ...

    ReplyDelete
  4. hello hardware.coder i saw this on alie ..i wonder what it is ... what do you think ??

    1Stk HC-11-USB CC1101 433Mhz


    https://nl.aliexpress.com/item/HC-11-USB-In-Line-433MHz-Wireless-Serial-Port-CC1101-Long-Distance-PC-End-Module/2044234088.html?spm=2114.010208.8.16.0FLa51

    ReplyDelete
    Replies
    1. Hello, sorry for long answer ;) About module that you proposed, in my opinion is quite limited to e.g. freq and modes, but it all depends what do you need it accually. I think you can't see full potential of cc1101 using another chip in the middle of which you don't have full control.

      I think it would be better for you to use sth. like this http://www.ebay.com/itm/CC1101-Wireless-TX-Module-and-Antenna-RF1100SE-Arduino-I2C-Flux-Workshop-/121878078777?hash=item1c607fe539:g:HycAAOSwpzdWqhuZ and connect it to arduino or even arduino Leonardo (which has the same mcu like in my dongle - atmega32u). Then use some cc1101 arduino library, I've seen that now there are some nice libraries on github that make things easier, so you could use your arduino nano with them.

      Delete