#119 Differences and similarities between the two
Recently I wrote about the pros and cons etc. about different programmers used to program embedded devices. I mentioned a few examples like ST-Link, PicKit and standard DIY programmers. Now since programmers work hand in hand with the programming software on your PC I decided to talk a bit about the 2 IDEs I use often. (Although you can easily setup platform IO with a compiler for embedded devices I will be focusing mostly on full IDEs but will make mentions to using text editors)
So I’ll start with the Arduino IDE. it’s simple to install and to get started with. There’s many libraries and there’s a wide support on the internet. Note: at least in my experience in South Africa at the public school I went to there was basically no interest or effort to promote Arduino and similar platforms. Looking back this was very disappointing since I’m 99% sure I would have gotten into Arduino much earlier in life if certain educational departments had made an effort in promoting Science instead of supporting political nonsense like the “science must fall” movement but I digress.
That being said Arduino is not all fun and games, it’s a great learning introduction tool but can promote bad code practices and reliance on libraries for work. Arduino also heavily promotes using easy functions instead of port manipulation methods… even in advanced projects… this can be a bit annoying especially when you want to use a library in a project with a different MCU and also when you want to keep code small and efficient. This can really bloat your MCU code and as you can imagine there is really not much room “literally” when programming embedded devices. Macros for port manipulation can really help but relying on digitalwrite(pin1); to pull a pin high or low can really cause some confusion later on
There may be more pros and cons not mentioned above but really I just want to get into the stuff that I can mention off the top of my head for this article.
Now switching to the free MPLABX IDE. I can say that the learning curve is quite steep but easy to get into with repetitive use. Once you get familiar with the layout you can start seeing quite a few pros compared to Arduino. having the ability to view the entire file structure in the IDE helps a ton. Also AVR has been integrated into MPLABX for some years now so you can easily program Arduino style. The IDE promotes professional main.c files and avr-main.c files which is very cool (I’m not really into ASM programming at least for now there’s a very big learning curve but one day I’ll get into it I hope 🙂 ) MPLABX also supports a huge variety of ICs and you can easily download updates for these as well as some libraries. Another pro is the GUI MCC (MPLAB Code Configurator) ok, ok I’m not a huge fan because I always somehow bloat up my project and break things but I can totally see how it could help by providing a GUI for setting clocks and bits etc. Another cool feature is that there are options for dark mode in the ide and it uses NetBeans.
There are a few downsides to the MPLABX IDE for example when using a 4k screen the Nebeans part always has blurry visuals now you can adjust the DPI but then all the text is super small and when adjusting the text it becomes inconsistent in certain places. Like for example the IDE text is small but your code text is big. This has always been an issue for me but I guess I’m just suffering from a 4k screen 🙂 Another issue is that I have always had to use expensive dedicated programmers when using MPLABX non of my DIY CH340N etc. programmers will work with MPLABX. Also programming AVR requires an AVR programmer so you can’t just use a PicKit3 for everything. Another pro is that it’s easy to choose compilers in a list. You cans install multiple compilers without issue. Another great feature is that you can install the so called MPLABEXT extension using visual studio code so you don’t have to use the IDE but can keep compatibility. Another cool feature is the ability to read and program the fuses or (configuration bits for PIC). Once again there may be some pros and cons not mentioned but I’m just writing this off the top of my head.
An honourable mention goes to the text editor approach. This is very light weight and generally bloat free and offers a lot of flexibility which makes using visual studio code a great choice but of course it’s not really a dedicated IDE.
Now to close off I will include to code samples to show the differences between the Arduino IDE and MPLABX IDE I will be programming an AVR device the ATtiny826 in the comparison examples.
Arduino blink code example including a blink without delay and a fast blink sample I made :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
/* * RoboTiny * * Arduino ATTINY3226-SU Tester * * @category Arduino ATTINY3226-SU Advanced Blink Sketch * @package C++ Alarm Sketch * @author C.A Torino * @version V1.0.0 * @since 13th Mar 2024 * @hardware ATTINY3226-SU Modified * @notes null Pinout of the ATTINY3226-SU: 20 pin SOIC, SSOP __ __ 1 VDD |1 \/20| GND 2 PA4 |2 19| PA3 (EXTCLK) 3 PA5 |3 18| PA2 4 PA6 |4 17| PA1 5 PA7 |5 16| PA0 (UPDI/RESET) 6 PB5 |6 15| PC3 7 PB4 |7 14| PC2 8 PB3 |8 13| PC1 9 (TOSC1)PB2 |9 12| PC0 10 TOSC2 PB1 |10 11| PB0 ------- Sketch uses 430 bytes (5%) of program storage space. Maximum is 8192 bytes. Global variables use 9 bytes (0%) of dynamic memory, leaving 1015 bytes for local variables. Maximum is 1024 bytes. */ #define D_LED_AMOUNT 1//Amount of LEDs bool AN_LED_BLINKING = false;//Is an LED blinking uint32_t previousMillis = 0;// will store last time LED was updated const uint16_t interval_time = 2000;// interval at which to blink (milliseconds) const uint16_t ON_TIME = 10;//Blink on time 10ms=good as well, 50=good flash const uint8_t LEDS[D_LED_AMOUNT] = { PIN3_bm//PA3 LED }; void setup() { PIN_config();//Initiate pin settings DISABLE_peripherals();//Disable unused } void DISABLE_peripherals() { ADC0.CTRLA = 0;//Disable ADC, saves ~230uA TCA0.SPLIT.CTRLA = 0; //If you aren't using TCA0 for anything TCB0.CTRLA = 0; //disable TCB0 USART0.CTRLA = 0;//disable usart SPI0.CTRLA = 0;//disable spi BOD.CTRLA = 0;//disable bod AC0.CTRLA = 0;//disable AC //DAC0.CTRLA = 0;//disable DAC (Not in AVR-2 series) } void PIN_config() { //all pins start as an input but it's good to make a human readable note VPORTA.DIR = 0b11111111; //read from right to left: 0b11111111 same as p7=1 p6=1 p5=1 p4=1 p3=1 p2=1 p1=1 p0=1; 1=output 0=input } void Blinking() { // check to see if it's time to blink the LED; that is, if the difference // between the current time and last time you blinked the LED is bigger than // the interval at which you want to blink the LED. uint32_t currentMillis = millis(); if (currentMillis - previousMillis >= interval_time) { // save the last time you blinked the LED previousMillis = currentMillis; // set the LED with the ledState of the variable: //digitalWrite(ledPin, ledState); VPORTA.IN |= LEDS[0];//toggle LED } } void Blinking_Fast() { uint32_t currentMillis = millis();//Get current millis if(AN_LED_BLINKING)//If an LED is blinking { if( (currentMillis - previousMillis) >= ON_TIME)//determine the on time and logic for rollover { AN_LED_BLINKING = false;// change the state of LED previousMillis = millis();// remember Current millis() time } } else { if( (currentMillis - previousMillis) >= interval_time)//determine the off time and logic for rollover { AN_LED_BLINKING = true;// change the state of LED previousMillis = millis();// remember Current millis() time } } for (uint8_t i = 0; i < D_LED_AMOUNT; i++) //loop through LEDS { if(AN_LED_BLINKING)//If the led is blinking { VPORTA.OUT |= LEDS[i];// LED HIGH } if(!AN_LED_BLINKING)//If the led is not blinking { VPORTA.OUT &= ~LEDS[i];// LED LOW } } } void loop() { //Blinking(); Blinking_Fast(); } |
MPLABX blink code example including a blink without delay and a fast blink sample I made :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
/* * MAIN Generated Driver File * * @file main.c * * @defgroup main MAIN * * @brief This is the generated driver implementation file for the MAIN driver. * * @version MAIN Driver Version 1.0.2 * * @version Package Version: 3.1.2 © [2024] Microchip Technology Inc. and its subsidiaries. Subject to your compliance with these terms, you may use Microchip software and any derivatives exclusively with Microchip products. You are responsible for complying with 3rd party license terms applicable to your use of 3rd party software (including open source software) that may accompany Microchip software. SOFTWARE IS ?AS IS.? NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP?S TOTAL LIABILITY ON ALL CLAIMS RELATED TO THE SOFTWARE WILL NOT EXCEED AMOUNT OF FEES, IF ANY, YOU PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. * File: avr-main.c * Author: User501 * * Created on November 4, 2024, 5:27 PM * * * RoboTiny * * MPLAB X ATTINY3226-SU Tester * * @category MPLAB X ATTINY3226-SU Advanced Blink * @package C++ Alarm Sketch * @author C.A Torino * @version V1.0.0 * @since 4th Nov 2024 * @hardware ATTINY3226-SU Modified * @notes null Pin out of the ATTINY3226-SU: 20 pin SOIC, SSOP __ __ 1 VDD |1 \/20| GND 2 PA4 |2 19| PA3 (EXTCLK) 3 PA5 |3 18| PA2 4 PA6 |4 17| PA1 5 PA7 |5 16| PA0 (UPDI/RESET) 6 PB5 |6 15| PC3 7 PB4 |7 14| PC2 8 PB3 |8 13| PC1 9 (TOSC1)PB2 |9 12| PC0 10 TOSC2 PB1 |10 11| PB0 ------- ATtiny826 Packs ATtiny_DFP (3.1.260) PICkit 5 (2.6.557) Compiler Toolchain XC8 (v2.50) [C:\Program Files\Microchip\xc8\v2.50\bin] Production Image: Optimization: +space +asm Device support information: ATtiny_DFP (3.1.260) Memory Data 1,024 (0x400) bytes Data Used: 1.3% Data Used: 13 (0xD) Free: 1,011 (0x3F3) Program 8,192 (0x2000) bytes Program Used: 6.3% Program Used: 516 (0x204) Free: 7,676 (0x1DFC) */ //this gives an accurate time #define F_CPU 2500000// 2.5Mhz; cpu frequency in Hz #include <avr/io.h>//AVR functions #include <avr/interrupt.h>// for interrupts #include <util/delay.h>//for delay #define D_LED_AMOUNT 1//define led amount const uint16_t interval_time = 2000;// interval at which to blink (milliseconds) const uint8_t LEDS[D_LED_AMOUNT] = { PIN3_bm//PA3 LED }; const uint16_t ON_TIME = 10;//LED on time 10ms=good as well, 50=good flash volatile uint32_t MIL_counter = 0;// millis counter variable uint32_t interval, nowmillis, previousMillis = 0;// for timing calculation in millis _Bool AN_LED_BLINKING = 0;//LED blinking set to false=0 // Init millis counter void MIL_init(void) { TCB1.CCMP = (F_CPU / 1000) - 1; // set TOP value (period) TCB1.CTRLA = TCB_ENABLE_bm; // enable timer/counter TCB1.INTCTRL = TCB_CAPT_bm; // enable periodic interrupt } // Read millis counter uint32_t MIL_read(void) { cli(); // disable interrupt for atomic read uint32_t result = MIL_counter; // read millis counter sei(); // enable interrupt again return result; // return millis counter value } // TCB0 interrupt service routine (every millisecond) ISR(TCB1_INT_vect) { TCB1.INTFLAGS = TCB_CAPT_bm; // clear interrupt flag MIL_counter++; // increase millis counter } void PIN_config() { //all pins start as an input but it's good to make a human readable note VPORTA.DIR = 0b11111111; //read from right to left: 0b11111111 same as p7=1 p6=1 p5=1 p4=1 p3=1 p2=1 p1=1 p0=1; 1=output 0=input } void DISABLE_peripherals() { ADC0.CTRLA = 0;//Disable ADC, saves ~230uA TCA0.SPLIT.CTRLA = 0; //If you aren't using TCA0 for anything TCB0.CTRLA = 0; //disable TCB0 USART0.CTRLA = 0;//disable USART SPI0.CTRLA = 0;//disable SPI BOD.CTRLA = 0;//disable bod AC0.CTRLA = 0;//disable ACl //DAC0.CTRLA = 0;//disable DAC (not used in Tiny-2 series) } void Blink_LED_Blocking() { VPORTA.OUT |= LEDS[0]; // LED HIGH _delay_ms(interval_time);//blocking delay VPORTA.OUT &= ~LEDS[0]; // LED LOW _delay_ms(interval_time);//blocking delay } void Blink_LED_Non_Blocking(uint32_t currentMillis) { if (currentMillis - previousMillis >= interval_time) {//set rollover and calculate delay time previousMillis = currentMillis;//set millis global var VPORTA.IN |= LEDS[0];//toggle LED } } void Blinking_Fast(uint32_t currentMillis) { if(AN_LED_BLINKING)//if LED is HIGH { if( (currentMillis - previousMillis) >= ON_TIME)//on time check rollover { AN_LED_BLINKING = 0;// change the state of LED previousMillis = currentMillis;// remember Current millis() time } } else { if( (currentMillis - previousMillis) >= interval_time)//check off time rollover { AN_LED_BLINKING = 1;// change the state of LED previousMillis = currentMillis;// remember Current millis() time } } for (uint8_t i = 0; i < D_LED_AMOUNT; i++) //0,1,2,3 first 4 { if(AN_LED_BLINKING)//if LED is blinking { VPORTA.OUT |= LEDS[i];// LED HIGH } if(!AN_LED_BLINKING)//if LED is not blinking { VPORTA.OUT &= ~LEDS[i];// LED LOW } } } int main(void) { //volatile uint32_t MIL_counter; PIN_config();//configure the pins DISABLE_peripherals();//disable unused MIL_init();//initiate harware timer TCB1 while(1) { nowmillis = MIL_read();// read custom DIY millis counter Blinking_Fast(nowmillis);//Blink LED fast //Blink_LED_Non_Blocking(nowmillis);//Blink LED non blocking delay //Blink_LED_Blocking();//Blink Blocking } } |