Tutorial Arduino programmieren,

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.

Re: Tutorial Arduino programmieren,

Beitragvon Mathias » 12. Mai 2018, 15:42 Re: Tutorial Arduino programmieren,

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 gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4107
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon kupferstecher » 16. Mai 2018, 09:45 Re: Tutorial Arduino programmieren,

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)"
kupferstecher
 
Beiträge: 142
Registriert: 17. Nov 2016, 11:52

Beitragvon Mathias » 24. Jul 2018, 20:26 Re: Tutorial Arduino programmieren,

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 gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4107
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Mathias » 28. Jul 2018, 19:47 Re: Tutorial Arduino programmieren,

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 gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4107
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon af0815 » 29. Jul 2018, 10:28 Re: Tutorial Arduino programmieren,

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).
af0815
 
Beiträge: 3412
Registriert: 7. Jan 2007, 10:20
Wohnort: Niederösterreich
OS, Lazarus, FPC: Win7/Linux (L stable FPC stable) per fpcup | 
CPU-Target: 32Bit (64Bit)
Nach oben

Beitragvon Timm Thaler » 29. Jul 2018, 11:52 Re: Tutorial Arduino programmieren,

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
Timm Thaler
 
Beiträge: 617
Registriert: 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
Nach oben

Beitragvon Mathias » 29. Jul 2018, 15:57 Re: Tutorial Arduino programmieren,

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 gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4107
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Mathias » 4. Aug 2018, 20:17 Re: Tutorial Arduino programmieren,

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 gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4107
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

• Themenende •
Vorherige

Zurück zu Sonstiges



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast

porpoises-institution
accuracy-worried