Wiki copymirror

This is a mirror of the wiki at pascal.chat. Editing, history and sign-in are there.

AVR Embedded Tutorial - Entry Lazarus and Arduino

Build Lazarus with AVR crosscompiler for Arduino Nano/Uno

mini

The tutorial was tested with:

The same tools are required under Windows , except the Linux Mint .

Tools required

Software

FPCUPdeluxe:

Arduino software:

Subversion:

pascal
sudo apt-get install subversion
pascal
sudo zypper install subversion

Should be installed automatically by FPCUPdeluxe, otherwise download and install from here.

Hardware

Install FPCUPdeluxe

It is best to copy the download of FPCUPdeluxe into a new empty folder and then start the copied file in the file manager with a double click. Linux asks if the file should be made executable, answer yes. The FPCUPdeluxe GUI should then start.

Build Lazarus with FPCUPdeluxe

Build trunk

If everything goes through without errors you get the current trunk from FPC and Lazarus. Normal desktop applications can now be created with this. There should be an icon for Lazarus_fpcupdeluxe on the Desktop.

https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png Note: Note: SVN repositories may experience difficulties. If so, don't give up, just try again later ;-) What also helps, run FPCUPdeluxe twice in a row. A non-current FPCUPdeluxe can also cause difficulties. If something doesn't work, you can ask in the Lazarus forum, the author is very helpful.

Build AVR Cross compiler

Press the Setup+ button in the Cross tab to open a dialog with further options. Set the following there:

Select the following check boxes in the Cross tab :

Press the Install compiler button and the cross compiler will be built. If everything went correctly, you can exit from FPCUPdeluxe.

Install drivers

Windows

Linux

Most of the time, the COM ports (USB-UART) have to be accessible by users. This is done with the following command:

pascal
sudo adduser $USER dialout

Prepare Lazarus

Start with F9

If you try to start with F9, you always get an error message. You can prevent this. Change the following in Lazarus:

So you can upload and start normally with F9.

But you have to consider that the debugger is also disabled if you then write a normal PC program with Lazarus!

Code tools

It is possible that the code tools cannot find the Atmega328p unit. If this happens, then the following step is necessary:

Readable ASM code creation

If you want to see the source as assembler code, the following step is necessary:

Faulty optimization

I have experienced a program not working properly because the compiler incorrectly optimised the code. So you should switch off code optimization with {$ O-} at the beginning of the program.

First project

Create a new project

https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png Note: Note: Arduino nanos have been in circulation with new bootloaders since the beginning of 2018. It may be enough to change this parameter: -b115200

More information in the Arduino Forum.

https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png Note: Note: The paths still have to be adapted to your own installation.

Windows: It must be avrdude with ".exe", "avrdude" alone is not enough, even if it is with Arduino without .exe.

https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png Note: Note: The Com-Port is called differently under Linux and Windows:

As a recommendation, I would take this project as a template and build all new projects on top of it. Setting the whole thing up for a new project each time is a bit tedious.

Start project

Nothing should now be standing in the way of your first blink program (source in the next section). Compile and upload the program with F9. If everything worked, the LED at pin 13 should flash about every second.

Different sources for getting started

Pin 13 blinker

pascal
program Project1;
     const
       BP5 = 5;      // Pin 13 of the Arduino
       dl = 250000;  // About 1/2 sec
    
       procedure delay(t : int32);
       var
         i : Int32;
       begin
         for i := 0 to t do begin
           asm
             nop;
           END;
         end;
       end;
    
     begin
       DDRB := DDRB or (1 shl BP5);      // switch port to output
       repeat
         PORTB := PORTB or (1 shl BP5);  // port to high
         delay(dl);                      // waiting
    
         PORTB := PORTB and not (1 shl BP5);  // port on low
         delay(dl);                           // waiting
       until 1 = 2;                           // infinite loop
     end.

Serial input/output

A terminal with the following settings is required for serial output:

pascal
program Project1;
     const
       CPU_Clock = 16000000;  // Arduino clock frequency, default 16MHz.
       Baud = 9600;           // baud rate
       Divider = CPU_Clock div(16 * baud) - 1;
    
       procedure UARTInit;
       begin
         UBRR0 := divider ;
    
         UCSR0A := (0 shl U2X0);
         UCSR0B := (1 shl TXEN0) or (1 shl RXEN0);
         UCSR0C := (% 011 shl UCSZ0);
       end;
    
       procedure UARTSendChar(c : char);
       begin
         while UCSR0A and (1 shl UDRE0) = 0 do begin
         end;
         UDR0 := byte(c);
       end;
    
       function UARTReadChar : char;
       begin
         while UCSR0A and (1 shl RXC0) = 0 do begin
         end;
         Result := char(UDR0);
       end;
    
       procedure UARTSendString(s : ShortString);
       var
         i : integer;
       begin
         for i := 1 to length(s) do begin
           UARTSendChar(s[i]);
         end;
       end;
    
     begin
       UARTInit;
       repeat
         if UARTReadChar = #32 then begin
           UARTSendString('Hello World!'#13#10);
         end;
       until 1 = 2;
     end.

Simple timer interrupt

Pin 13 is switched to HIGH every second.

pascal
program Project1;
     const
       BP5 = 5;  // Pin 13 of the Arduino
    
       procedure sei;  assembler;
       asm
         Sei
       END;
    
       procedure Timer2_Interrupt;  alias : 'TIMER2_OVF_ISR';  interrupt;  public;
       const
         counter : integer = 0;
         cl = 16000000 div 1024 div 256 div 2;  // 16'000'000Hz / Clock / TCNT / 2 = 0.5sec
       begin
         Inc(counter);
         if count = cl then begin
           PORTB := PORTB or (1 shl BP5);
         end;
         if count > = cl * 2 then begin
           PORTB := PORTB and not (1 shl BP5);
           count := 0;
         end;
       end;
    
     begin
       DDRB := DDRB or (1 shl BP5) ;  // Pin 13 output
    
       TCCR2A := %00;             // Normal timer
       TCCR2B := % 111;           // clock / 1024
       TIMSK2 := (1 shl TOIE2);   // enable timer2 overflow interrupt
       sei();                     // turn on interrupts
    
       repeat
         // do something
       until 1 = 2;
     end.

Reinstalling the OS

Conclusion

For those who have already programmed with the Arduino IDE, they will have certainly found that there are a lot of ready-made libraries. You can code something very easily and quickly, but there is a lot hidden there.

With Lazarus, you have to do everything yourself and thus deal with the registers of the AVR microcontroller. But this also has a big advantage, you know what you are doing. You can also generate more optimized code in this way.

Thank you

The most important thing at the end:

See also


From the Free Pascal wiki, page "AVR Embedded Tutorial - Entry Lazarus and Arduino", as the Internet Archive kept it on 2024-09-14, last changed on 2020-12-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 1, last changed by WikiArchive .