LinuxCNCKnowledgeBase | RecentChanges | PageIndex | Preferences | LinuxCNC.org

AVR as LinuxCNC Peripheral


Reference Material:

AVR1600: Using the XMEGA Quadrature Decoder

AVR492: BLDC Motor control in sensor mode using AT90PWM3/3B

AVR1607: Brushless DC Motor (BLDC) Control in Sensor mode using ATxmega128A1 and ATAVRMC323

AVR435: BLDC/BLAC Motor Control Using a Sinus Modulated PWM Algorithm on AT90PWM3B

AVR325: High-Speed Interface to Host Enhanced Parallel Port (EPP) using tinyAVR and megaAVR devices

XMega100 Breakout
http://www.olimex.com/dev/index.html (click AVR, find AVR-HX128A1)

Level Translators

for experiments:

SN74CBTD3861: 10 bit fet bus switch with level shifting


GTL2010: 10bit, 1.0 - 5.0V, no dir pin


Some of the Todo items:

Design a 5V to 3.3V PC parallel port to ATxmega interface

Develop software for LinuxCNC EPP master and ATxmega EPP slave, layout register or command/data protocol

SPP experiment

 component spp       "u32 output to parallel port";

 pin in u32 sppin;   "Input to send to parallel port"
 pin out u32 meter;  "Output pin allows Halmeter to see what the port address is"
 function _;
 license "GPL";
 #include <asm/io.h>  // Needed for outb

 int ioaddr;
 RTAPI_MP_INT(ioaddr,"Address of parallel port");  // See RTAPI_MP's in http://www.linuxcnc.org/docview/html/, still seems like magic to me (KW)
    outb(sppin, ioaddr);  // Loads Data port, see http://www.beyondlogic.org/spp/parallel.htm#5
    meter = ioaddr;       // Lets Halmeter check ioaddr

.hal file commands
 loadrt spp ioaddr=0x21c0 // Only takes one address at this time
 addf spp.0                     servo-thread
 net SpindleSpeedPWMcmd   conv-float-u32.0.out      spp.0.sppin

In my setup, the new data was on the parallel port output immediately upon loading the data register.

Develop ATxmega single PWM/dir (and step/dir?) app for brushed DC motor amp, and amp hardware (3.3V to 5V) interface

(Post AVR specific information here, such as LinuxCNC component programs, AVR code, or AVR to hardware and LinuxCNC interface information)

Develop ATxmega single quadrature decoder/counter app, and encoder hardware interface

Develop ATxmega single BLDC three phase half bridge app with Hall input, and hardware

Integrate encoder data for sinus BLDC output

Explore scaling motor/encoder system to three axes per ATxmega

the 128A1 has 6 timers/counters -> but only one 3 phase motor can be used
suggestion: put 3 Atmels on a PCI board
an old design for a pci experimental board (TTL 5V)

To have a fast 3.3V interface consider an FPGA.



jjf 2011-02-26
The AVR32 chips may be usefull for motor control with a real time ethernet connection.
Atmel has a nice gui-based IDE (Eclipse), which works with linux.
I have installed the x86_64 2.6 version, the AVR UC3 Software Framework 1.7.0
on Ubuntu 10.10 and testet some compiled examples on a EVK1100 board.
(this board has no qdec!)
To download the binary use dfu-programmer from ubuntu.
First convert the elf file to hex and connect the board with usb to ubuntu box.
Press reset button, press joystick, release reset, release joystick to activate the dfu-bootloader.
avr32-objcopy -O ihex eth-01.elf eth-01.hex
dfu-programmer at32uc3a0512 erase
dfu-programmer at32uc3a0512 flash --suppress-bootloader-mem eth-01.hex
dfu-programmer at32uc3a0512 reset
Press and release the reset button and your code runs.
upload:macb_example.tar.gz contains small modification to the atmel example to get an udp response.
(this code is pre alpha!, but tcpdump has seen the response packet)
There is a Appnote: "Space Vector Modulation for Motor Control ..." for this board

ATmega32 (8bit) with Modbus

This section will cover using an ATmega32 with a Modbus RTU connection similar to a VFD Modbus application. So far, I have an RS232 connection from a serial port on the LinuxCNC PC running to a MAX232 based RS232 to TTL converter, then to the ATmega32 serial port. The LinuxCNC software components are a serial Modbus driver based on the gs2_vfd.c driver: http://git.linuxcnc.org/gitweb?p=linuxcnc.git;a=blob;f=src/hal/user_comps/gs2_vfd.c;h=17ed97b78e681c673ab768eb2e0e62bb0b7daf73;hb=e0fbe2669c1bc7b320b738f72ee15abe868aa5a9 , and a set of configuration files to HAL connect the driver pins to a machine application.

The AVR components are the FreeMODBUS AVR API: http://freemodbus.berlios.de/index.php , and the demo.c program included in the FreeMODBUS package.

The LinuxCNC driver, let's say m32_mbrtu.c , could be made by copying the gs2_vfd.c file linked above to your LinuxCNC subdirectory such as ~/linuxcnc/m32_mbrtu/ . Then copy modbus.c , modbus.h , and Makefile from here: http://git.mah.priv.at/gitweb/vfs11-vfd.git/tree (thanks to Michael Haberler). Rename gs2_vfd.c to m32_mbrtu.c and edit to change the names and variables to match the m32's demo program. Currently, the demo has four 16 bit Input registers starting at register address 1000 (0x03E7) that can be read with Mobus function 4, so the "retval = read_holding_registers(param, slavedata->slave,..." will need to be changed to "retval = read_input_registers(param, slavedata->slave,...". The write function is not needed for the demo program until the demo has writable registers. modbus.c and modbus.h are left alone. The Makefile needs to have every "vfs11_vfd" replaced with "m32_mbrtu", then run "make && sudo make install". If successful, you will have an HAL userspace component that can be loaded in a .hal file with "loadusr m32_mbrtu ..." plus the proper option settings. Next, a LinuxCNC configuration needs to be added to ~/linuxcnc/configs/ and the loadusr added to a .hal file. For testing the pins don't need to be connected because we can see the register values with halmeter or halscope.

For the m32 part, download the FreeMODBUS AVR package: http://freemodbus.berlios.de/index.php?idx=5 . I created a m32_mbdemo directory under ~/linuxcnc/ to make ~/linuxcnc/m32_mbdemo/, then I copied from the package's linux directory; demo.c, Makefile and /port . demo.c and /port should not need any changes. Makefile needs to have the .cof bits removed, such as remove "$(TARGET).cof" from "all: $(TARGET).elf $(TARGET).cof $(TARGET).hex $(TARGET).eep". cof seems to have something to do with debugging and isn't compatible or essential to this project. "MCU = atmega168" needs to be changed to match the processor being used, "MCU = atmega32" in my case. "CC=...", "OBJCOPY=...", and "AVRDUDE=..." need to be changed to point to the location of these programs on your PC. I used a 10MHz crystal, so I changed "-DF_CPU=20000000UL" to "-DF_CPU=10000000UL", plus changed the fuse bits to match. I believe I removed all of the "../.." because I copied my files to different directory locations. It might be best to try to use the standard locations. The flash section: "flash: $(AVRDUDE) -p m168 -c stk200 -U flash:w:$(TARGET).hex" needs to be changed to match your device and programmer, I used "flash: $(AVRDUDE) -p m32 -c usbtiny -U flash:w:$(TARGET).hex". "make" should compile and create the needed files. "make flash" should upload the hex file to the AVR. It is mentioned in the FreeMODBUS demo documentation that EEPROM is used to store some data, but I didn't see that the EEPROM space was programmed after the upload, and the demo functions, so this is a mystery to me.

After starting LinuxCNC, the m32_mbrtu component will poll the serial port. This can be verified using a serial port sniffer. I used jpnevulator: http://jpnevulator.snarl.nl/ (warning: one of the options uses an offensive, to me at least, term). jpnevulator seems to need to be started (in its own terminal) before the application being sniffed, so start LinuxCNC after the sniffer. Also transmit and receive need to be connected together (after disconnecting the ATmega somewhere down the line) to loop the Tx back to the Rx, because the sniffer only sniffs the receive input. The sniffer should show something like "0A 04 03 E7 00 04..." repeated as long as LinuxCNC is running. "A0" is the slave ID, 10 in this case. "04" is the Modbus function 4, then two bytes of register address, 1000 or "03 E7" in this case. Then two bytes of the number of registers to send, or 4 in this case. Then two bytes for the packet CRC check sum. This shows what is being sent to the ATmega, but doesn't consider what the ATmega will send back. For that we remove tha Tx Rx jumper and connect the serial cable back on the ATmega. The sniffer should then show the return packets, or some thing like "0A 04 xx xx 00 00 00 00 00 ...". The "xx xx" will be the changing value of register 1. The other registers remain at 0. If you get "0A 84 xx", this the ATmega telling you that there is an error with the exception code of "xx". The codes can be seen here: http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b.pdf , on page 16 (section 6.4). I used modpoll to fill in for LinuxCNC as a Modbus master during trouble shooting: http://www.modbusdriver.com/modpoll.html . This will show the return register values, but it might also be handy to sniff modpoll to get more details. Just remember to start the sniffer in its own terminal before starting modpoll.

There is a lot more to do to make a useful application, but this might be a base to start from. The above is more of a note to myself to remind me of what I did to make the demo work. There are most likely, bits missing, not accurate, or poorly done. If anyone can improve this text, please feel free to edit this section, Kirk Wallace 2011/03/24.

LinuxCNCKnowledgeBase | RecentChanges | PageIndex | Preferences | LinuxCNC.org
This page is read-only. Follow the BasicSteps to edit pages. | View other revisions
Last edited January 2, 2017 10:27 pm by KimK (diff)
Published under a Creative Commons License