Grbl
Grbl is a high performance CNC controller. It is used on a lot of small scale CNC machines and is the motion control code behind a lot of 3D printers. It was originally targeted at the Arduino 328p hardware (UNO). It is developed by Sungeun “Sonny” Jeon. He is a good friend. He is always very helpful and this port would not have been possible without the quality of his code and his advice.
PSoC Mixed Signal Controller
I love working with the PSoC (Programmable System on Chip) family of micro controllers. You can configure them on the fly with many analog and digital components. The analog components are not basic ADCs and DACs, you have OpAmps, PGAs, filters, MUXs and more. The digital blocks includes basic logic gates, all the way up to FPGA like components you program yourself in Verilog.. There are over 200 ready to use components you can wire together on the chip.
I have always used them for small prototype projects, but wanted to test my skills by porting a major project like Grbl. At the same time I wanted to take advantage of the features of the PSoC. The dev board I used was the CY8CKIT-059. This has ARM Cortex M3 processor a lot of I/O and costs less than $10! It has a built in programmer and debugger.
PSoC Advantages
Here is a comparison between the the ATMega 328p (Arduino UNO) and the PSOC5
PSoc 5 |
ATMega328p (UNO) |
|
CPU |
32 bit (ARM Cortex M3) |
8 bit |
Speed |
Up to 80MHz |
16MHz Typ. |
Flash (program size) |
256k |
32k |
RAM |
64k |
2k |
EEPROM |
2k |
1k |
I/O |
up to 62 |
14 |
Flexibility
Grbl’s flexibility allows you to tailor it to your hardware. With a few limitations, you can move the pins around and change things like whether switches are active low or high. This is all done using #define values in configuration files. That is great, but the code gets a little messy every time you access hardware. It has to do a little logic gymnastics each time.
With PSoC you can do all of that in a visual schematic and pin wiring feature. Here is a PDF of my schematic. Have you ever swapped transmit and receive on a UART? In PSoC you can just swap the pins on the schematic.
Here is an example of the difference in firmware code.
Grbl on 328p
uint8_t limits_get_state() { uint8_t limit_state = 0; uint8_t pin = (LIMIT_PIN & LIMIT_MASK); if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { pin ^= LIMIT_MASK; } if (pin) { uint8_t idx; for (idx=0; idx<N_AXIS; idx++) { if (pin & get_limit_pin_mask(idx)) { limit_state |= (1 << idx); } } } return(limit_state); }
Grbl on PSoC
uint8_t limits_get_state(){ return Status_Limit_Read(); }
Special Hardware Usage
I used some special features to move functions out of code and onto the hardware. One of them was the step pulse. Stepper drivers typically require a pulse of a minimum length to take a step. In normal hardware you have to raise the pin, then figure out a way to turn it off after a given period of time. This is typically done via an interrupt. It works fine, but the code is messy and interrupts can cause timing issues. PSoC control registers have a pulse feature that automates this. You attach a clock and the clock determines the length of the pulse. The code sets it and the hardware clears it. It looks like this on the schematic.
Another feature I used was hardware switch debouncing. This can be done completely in hardware. See the image below. The clock sets the debounce time. The debouncers are all fed into a status register where they are read as a single value. There are digital “nots” after the debouncers because my switches close to ground. The firmware could invert the logic, but it is so much easier to read on the schematic. It then feeds an interrupt.
If you would rather do this with an analog filter, you can design custom filters in the hardware. You could fine tune the filter right from your keyboard.
LCD
PSoC has a built in character LCD Component that makes using and LCD very easy. The code for the LCD is in the main loop and not an interrupt. This allows the time critical stuff to have higher priority. I used an interrupt to just set a flag so the LCD does not update every time through the main loop. I found the LCD to be an awesome debugging tool. I could display stuff while the code is running.
I also used a hardware Quadrature Decoder for the LCD rotary knob. This works great to monitor the encoder in hardware. I just need to read the value in the LCD update routine. The clock feature on the QuadDec is a debouncer, which helped debounce my mechanical encoder.
Next Steps
I have been testing for a while and so far it is working great. I also have some plans to use the extra power on some cool projects.
Here is the code on GitHub
Here is a picture of my test setup.