Tutorial Arduino programmieren,

Antworten
Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Tutorial Arduino programmieren,

Beitrag von Mathias »

Nicht mit den in den Ports integrierten, diese waeren nur aktiv, wenn das Port-Register 1 waere (bei Eingang).

Dies stimmt auch wieder.

Hier muss man im Schaltplan explizit Pullups vorsehen fuer die High-Pegel.

Dies wird wohl der Grund sein, das man bei I²C PullUps verlöten muss ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Tutorial Arduino programmieren,

Beitrag von kupferstecher »

Soviel ich weiß sind die Werte der Pullups von der Leitungslänge und der Anzahl Busteilnehmer/Eingangsimpedanzen abhängig. Interne Pullups passen daher normalerweise nicht. Ist wohl eine Frage der Zuverlässigkeit, prinzipiell funktionieren täte es vielleicht auch mit den internen.

Edit:
Aus der I²C-Spezifikation (https://www.nxp.com/docs/en/user-guide/UM10204.pdf)
"The external pull-up devices connected to the bus lines must be adapted to accommodate the shorter maximum permissible rise time for the Fast-mode I2C-bus. For bus loads up to 200 pF, the pull-up device for each bus line can be a resistor; for bus loads between 200 pF and 400 pF, the pull-up device can be a current source (3 mA max.) or a switched resistor circuit (see Section 7.2.4)"

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Tutorial Arduino programmieren,

Beitrag von Mathias »

Wieso wurde bei den Array ein len übergeben ?
http://wiki.freepascal.org/AVR_Embedded ... Cbertragen

So wie ich festgestellt habe, kann man auch bei dem AVR mit Length die Array-Länge abfragen.

Code: Alles auswählen

  procedure Test(const p: array of TPara);
  begin
    for i := 0 to Length(p) - 1 do  ....

Nur SetLength geht nicht, da dies dynamisch ist.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Tutorial Arduino programmieren,

Beitrag von Mathias »

Ich habe mal ein paar fertige Beispiele auf GITHUB hoch geladen.

https://github.com/sechshelme/AVR-Lazarus

@Timm
Hat dies ein spezieller Grund ?
Wieso wurde bei den Array ein len übergeben ?
http://wiki.freepascal.org/AVR_Embedded ... Cbertragen
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Tutorial Arduino programmieren,

Beitrag von af0815 »

Wenn man die Länge mit übergibt, so kann man bestimmen wie viele Daten übertragen werden. Bsp: wenn ich aus einem größeren Array nur einen bestimmten Teil übertragen will.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Tutorial Arduino programmieren,

Beitrag von Timm Thaler »

Mathias hat geschrieben:Hat dies ein spezieller Grund ?


Das ist einer davon:

af0815 hat geschrieben:Wenn man die Länge mit übergibt, so kann man bestimmen wie viele Daten übertragen werden. Bsp: wenn ich aus einem größeren Array nur einen bestimmten Teil übertragen will.


Wie Du an "var" bei der Übergabe siehst, wird nicht das Array übergeben, sondern die Referenz auf das Array (für C-Freaks: der Pointer). Das ist wichtig, sonst baut der Compiler einer Routine ein, die das Array an eine andere Speicherstelle kopiert, unnötigerweise.

So arbeitet der Compiler mit dem originalen Array, in meinem Fall ein Buffer für den nRF-Sender / Empfänger. Dieses Array ist 32 Byte lang. Manchmal wird aber nur die Adresse von 5 Byte gesendet. Die Daten werden als dynamische Payload gesendet, die kann 2 bis 32 Byte haben. Natürlich könnte ich das mit variablen Stringlängen machen, dann muss der Compiler aber ständig neue Strings unterschiedlicher Länge anlegen, der Speicher wird fragmentiert. Alles unnötig, wenn man einen festen Buffer verwendet.

Ausserdem - in meinem Fall sind die gleich lang - können dout und din unterschiedlich groß sein. Eine universelle Routine müsste hier abfragen, welches kleiner ist und dann die Länge auf das kleinere Array setzen.

Und dann baut der Compiler hier noch lustigen Schrott ein:

Code: Alles auswählen

# [54] for cnt := 0 to length(dout) - 1 do begin
   ldi   r18,1
   add   r22,r18
   adc   r23,r1
   subi   r22,1
   sbc   r23,r1


Da wird also der Index des letzten Elements als Word übergeben, dann auf den Index noch 1 draufgerechnet, um die Länge zu bekommen, um es gleich darauf wieder abzuziehen, und später wird nur r22, also Byte verwendet. Übergebe ich dagegen die Länge selbst, reduziert sich das zu:

Code: Alles auswählen

# [81] for cnt := 0 to len - 1 do begin
   dec   r20

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Tutorial Arduino programmieren,

Beitrag von Mathias »

Wie Du an "var" bei der Übergabe siehst, wird nicht das Array übergeben, sondern die Referenz auf das Array (für C-Freaks: der Pointer). Das ist wichtig, sonst baut der Compiler einer Routine ein, die das Array an eine andere Speicherstelle kopiert, unnötigerweise.


Folgendes funktioniert auf dem AVR mit const und var.

Code: Alles auswählen

type
  TPara = record
    start, stop: Int16;
  end;
 
var
  ar1: array[0..2] of TPara = ((start: 10; stop: 20), (start: 20; stop: 30), (start: 40; stop: 50));
  ar2: array[0..0] of TPara = ((start: 111; stop: 222));
  ar3: array[0..1] of TPara = ((start: 3333; stop: 4444), (start: 5555; stop: 6666));
 
  procedure Test(const p: array of TPara);
  var
    i: Int16;
    s: ShortString = '';
  begin
    for i := 0 to Length(p) - 1 do begin
      str(p[i].start: 6, s);
      UARTSendString(s);
      str(p[i].stop: 6, s);
      UARTSendString(s);
    end;
  end;
 
begin
  Test(ar1);
  Test(ar2);
  Test(ar3);


Mache ich aber

Code: Alles auswählen

procedure Test(p: array of TPara)
kommt nur ein "Internal error 2017091103".

Nehme ich in der Procedure auch auch eine statisch Array, dann gest es ohne var/const, so wie du es geschrieben hast.

Code: Alles auswählen

type
  TPara = array[0..3] of Byte;
var
  ar1: TPara = (1,2,3,4);
  ar2: TPara = (5,6,7,8);
 
  procedure Test(p: TPara);
  var
    i: Int16;
    s: ShortString = '';
  begin
    for i := 0 to Length(p) - 1 do begin
      str(p[i]: 6, s);
      UARTSendString(s);
    end;
  end;
 
begin
  Test(ar1);
  Test(ar2);


Anscheinend ist in einem var/const Parameter der einzige Ort, wo AVR mit dynamischen Arrays umgehen kann.
Wobei dynamisch ist sie ja nicht, da nur die Referenz übergeben wird.
Dies hatte ich zuerst auch nicht gewusst, deshalb hatte ich am Anfang eine Array via Pointer der Procedure übergebeben, dies hatte ich erst in deinem SPI-Tutorial gesehen.
Wen ich var/const weglasse, müsste innerhalb der Procedure eine dynamische Array erzogen werden, aber die geht nicht, da der AVR kein Speicher dynamisch verwalten kann.

Stimmt diese Behauptung, AVR kann mit allem nicht umgehen, was einen Heap braucht ?
Aber einen Stack kennt er ?

So arbeitet der Compiler mit dem originalen Array, in meinem Fall ein Buffer für den nRF-Sender / Empfänger. Dieses Array ist 32 Byte lang. Manchmal wird aber nur die Adresse von 5 Byte gesendet. Die Daten werden als dynamische Payload gesendet, die kann 2 bis 32 Byte haben.
Dies ist natürlich ein Argument.

Wie findest du diese Lösung ?
Dies wäre flexibler, da man x-beliebig Daten übergeben kann.
Wobei die dynamische Array auf dem AVR nicht geht.

Code: Alles auswählen

procedure Ausgabe(p: PByte; len: integer);
var
  i: integer;
begin
  for i := 0 to len - 1 do begin
    Write(p[i], ' ');
  end;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
const
  s = '12345678';
  a: array[0..3] of byte = (65, 66, 67, 68);
  a2: array[0..1, 0..1] of Char = ((#97, #98), (#99, #100));
var
  ad: array of byte;
  i: integer;
begin
  Ausgabe(@s[1], Length(s));
  WriteLn();
 
  Ausgabe(@a, SizeOf(a));
  WriteLn();
 
  Ausgabe(@a2, SizeOf(a2));
  WriteLn();
 
  SetLength(ad, 10);
  for i := 0 to Length(ad) - 1 do begin
    ad[i] := i;
  end;
  Ausgabe(Pointer(ad), Length(ad));
end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Tutorial Arduino programmieren,

Beitrag von Mathias »

Ich habe gerade ein Tutorial hochgeladen, dort wird gezeigt, wie man ein Schieberegister 74HC595 über SPI ansteuern kann.
Die Geschwindigkeit ist etwa den Faktor 10 schneller als ein ShiftOut.
Ideal für jemanden, der ein grosses Multiplex ansteuern will.

http://wiki.freepascal.org/AVR_Embedded ... egister/de
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Tutorial Arduino programmieren,

Beitrag von Mathias »

So unbekannt, ist das Tutorial doch nicht. 8)

https://www.mikrocontroller.net/topic/457722#5526783
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Tutorial Arduino programmieren,

Beitrag von pluto »

Dort gibt es immer einige Unfreundliche "Mitglieder".... wie ich finde, aber sowas wie hier:
Pascal auf AVR8 ist mir fremd, deshalb vorab die Bitte um
Entschuldigung, falls ich falsch liege

Geht ja noch, aber ich habe dort auch schon andere Sachen gelesen....

Ist doch schon mal was, dass auch dort das Lazarus-Forum mehr zur Geltung kommt.

Ich teste gerade STM32(habe ein STM32F303 Discovery Board und ein paar STM32F103) mit Arduino kann ich sie schon Programmieren und neuerdings auch mit Rust, mit Lazarus/FPC werde ich es mir auch noch mal anschauen...
MFG
Michael Springwald

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Tutorial Arduino programmieren,

Beitrag von Socke »

Timm Thaler hat geschrieben:Und dann baut der Compiler hier noch lustigen Schrott ein:

Code: Alles auswählen

# [54] for cnt := 0 to length(dout) - 1 do begin
   ldi   r18,1
   add   r22,r18
   adc   r23,r1
   subi   r22,1
   sbc   r23,r1


Da wird also der Index des letzten Elements als Word übergeben, dann auf den Index noch 1 draufgerechnet, um die Länge zu bekommen, um es gleich darauf wieder abzuziehen, und später wird nur r22, also Byte verwendet. Übergebe ich dagegen die Länge selbst, reduziert sich das zu:

Code: Alles auswählen

# [81] for cnt := 0 to len - 1 do begin
   dec   r20

Deswegen verwendet man bei Arrays _immer_ die Funktionen low() und high().
Siehe FPC-Quelldate rtl/inc/dynarr.inc

Code: Alles auswählen

function fpc_dynarray_length(p : pointer) : tdynarrayindex;[Public,Alias:'FPC_DYNARRAY_LENGTH']; compilerproc;
  begin
     if assigned(p) then
       fpc_dynarray_length:=pdynarray(p-sizeof(tdynarray))^.high+1
     else
       fpc_dynarray_length:=0;
  end;
 
 
function fpc_dynarray_high(p : pointer) : tdynarrayindex;[Public,Alias:'FPC_DYNARRAY_HIGH']; compilerproc;
  begin
     if assigned(p) then
       fpc_dynarray_high:=pdynarray(p-sizeof(tdynarray))^.high
     else
       fpc_dynarray_high:=-1;
  end;
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Tutorial Arduino programmieren,

Beitrag von Mathias »

Siehe FPC-Quelldate rtl/inc/dynarr.inc

So wie ich das sehe, bezieht dich dies auf dynamische Arrays, mit denen kann der AVR sowieso nicht umgehen.
Sind die Functionen Lenght, High und Low nicht nur Alias ?

Dort gibt es immer einige Unfreundliche "Mitglieder".... wie ich finde, aber sowas wie hier:

Die ist dort leider Standard. Aber immerhin, man bekommt sehr schnell Antwort.
Das Board ist leider auch sehr eigenwillig, man kann sich irgendwie nicht mal richtig registrieren. Irgendwie ist das ganze mit Facebook verknüpft.
Und auch die Darstellung ist sehr altmodisch.

Ich teste gerade STM32(habe ein STM32F303 Discovery Board und ein paar STM32F103) mit Arduino kann ich sie schon Programmieren und neuerdings auch mit Rust, mit Lazarus/FPC werde ich es mir auch noch mal anschauen...
Mit Arduino/Sloeber ist der STM gut unterstützt. Mit FPC geht es montan nur über den Umweg von MSEide. fpcupdeluce unterstützt dies leider (noch) nicht, so das man mit Lazarus arbeiten könnte.
Ich muss nochmals versuchen bei im englischen Forum nachzufragen. Ich habe schon mal probiert, aber es kam keine Antwort.
Ich könnte mal DonAlfredo eine PM schocken, vielleicht hat er meine Anfrage nur übersehen. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Tutorial Arduino programmieren,

Beitrag von pluto »

Mit Arduino/Sloeber ist der STM gut unterstützt. Mit FPC geht es montan nur über den Umweg von MSEide. fpcupdeluce unterstützt dies leider (noch) nicht, so das man mit Lazarus arbeiten könnte.

Ja, dass war das erste was ich versucht habe, es erst mal über Arduino zu laufen zu bekommen.

Ein Punkt ist wohl bei den STM32 Sachen, du musst erst alles "Einschalten". Am Anfang ist erst mal alles ausgeschaltet.

Ich muss nochmals versuchen bei im englischen Forum nachzufragen. Ich habe schon mal probiert, aber es kam keine Antwort.

Was für ein Problem hast du den bzw. was für eine Frage? Vielleicht kann ich sie "weiterleiten".... kenne da jemand der sich mit den STM32 Sachen sehr gut auskennt. Der ist aber nicht Mitglied hier im Forum.

Was ich ja so gras finde ist das Preis/Leistungsverhältnis zwischen dem STM32 und den Arduinos....
Aber dazu könnten wir ja noch mal ein Extra Thread machen.
MFG
Michael Springwald

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Tutorial Arduino programmieren,

Beitrag von Mathias »

Was für ein Problem hast du den bzw. was für eine Frage? Vielleicht kann ich sie "weiterleiten".... kenne da jemand der sich mit den STM32 Sachen sehr gut auskennt. Der ist aber nicht Mitglied hier im Forum.


http://forum.lazarus.freepascal.org/ind ... 866.0.html

Erst muss mal der Cross-Compiler für Lazarus her. Fragen, welche dann den STM32 anbelangen kommen dann erst später.

Ein Punkt ist wohl bei den STM32 Sachen, du musst erst alles "Einschalten". Am Anfang ist erst mal alles ausgeschaltet.
Das habe ich auch schon bemerkt, aus diesem Grund habe ich es hier auch vermerkt: http://wiki.freepascal.org/ARM_Embedded ... _output/de

Was ich ja so gras finde ist das Preis/Leistungsverhältnis zwischen dem STM32 und den Arduinos....
Aber dazu könnten wir ja noch mal ein Extra Thread machen.
Es ist nicht nur der Preis, auch Power hat er mehr, immerhin ist er mit 72MHz getaktet und erst noch ist er 32Bit.
ATtiny/Atmega max 20MHz, nur 8Bit.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Tutorial Arduino programmieren,

Beitrag von mse »

Mathias hat geschrieben:Erst muss mal der Cross-Compiler für Lazarus her.

Funktionieren die Compiler-Umgebungen von hier:
https://sourceforge.net/projects/mseide ... membedded/
https://sourceforge.net/projects/mseide ... pcrossarm/
nicht?
Für ein STM32 Discovery Board gibt es eine erprobte Lösung hier:
viewtopic.php?f=9&t=11264&start=35

Antworten