Der AVR-/ARDUINO-Faden

Der chaotische Hauptfaden

Moderatoren: Heaterman, Finger, Sven, TDI, Marsupilami72, duese

ch_ris
Beiträge: 3029
Registriert: Mo 30. Nov 2015, 10:08

Re: Der AVR-/ARDUINO-Faden

Beitrag von ch_ris »

langer text, timeout, text weg :(
deshalb jetzt ganz kurz:
warum ist mein Vorschlag scheise, 1 can modul per expander (kascade) auf die 24 akkus zu verteilen?
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

ch_ris hat geschrieben: Mo 9. Jan 2023, 07:04 langer text, timeout, text weg :(
deshalb jetzt ganz kurz:
warum ist mein Vorschlag scheise, 1 can modul per expander (kascade) auf die 24 akkus zu verteilen?
Weil die Teilnehmer auf dem CAN-BUS regelmäßig Daten senden. Die werden dann übersehen, und alle Teilnehmer benötigen alle 100ms einen Datensatz damit die wach bleiben.
Das CAN-Modul puffert die Daten und kann auch empfangen wenn der MC grade was anderes macht.
Der MCP2515 kann sogar einen Interrupt erzeugen auf einen bestimmten Inhalt.
ch_ris
Beiträge: 3029
Registriert: Mo 30. Nov 2015, 10:08

Re: Der AVR-/ARDUINO-Faden

Beitrag von ch_ris »

danke für die Erklärung, dachte die sollen nur gepollt werden.
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Gibt es in Visual Code / Platformio eine Möglichkeit Inhalte der Zeiger/ Klassen/Variablen sichtbar zu machen? So das ich dann sehe wo zB ein Zeiger hin geht und das es ein Zeiger ist?
Kenakapheus
Beiträge: 173
Registriert: Fr 1. Jan 2016, 20:43
Wohnort: Freie Feldlage (Ja, da wo das Treffen ist))

Re: Der AVR-/ARDUINO-Faden

Beitrag von Kenakapheus »

Meinst du jetzt die Adresse anzeigen?
Oder willst du wissen auf welche spezifische variable ein pointer Zeigt?
Zweiteres wird vermutlich nicht gehen, a das IDE dafür den gesamten Code simulieren müsste um zu wissen wo welcher pointer wann hin zeigt.

- Phiona
Kenakapheus
Beiträge: 173
Registriert: Fr 1. Jan 2016, 20:43
Wohnort: Freie Feldlage (Ja, da wo das Treffen ist))

Re: Der AVR-/ARDUINO-Faden

Beitrag von Kenakapheus »

Hightech hat geschrieben: So 8. Jan 2023, 20:09 Ich renne immer gegen alle Wände.
Vielleicht schaut jemand mal rein?
...
Ich habe mir das mal angesehen und versucht so umzubauen wie ich die Aufgabe verstehe:

Mein Konzept ist das jeder MCP2515 ein eigenes Objekt bekommt, welches schon den Pointer zum PCF8574 und die Pin Nummer kennt und sich darum kümmerst den CS pin zu setzen.
Nachteil davon ist das es relativ viel Speicher benötigt und nicht ohne weiteres mit Interrupts funktioniert.
Außerdem wird es so etwas mehr Aufwand Broadcast zu machen, daher habe ich das erstmal gelassen.
das Interrupt Problem existiert aber in jedem Fall und lässt sich potentiell lösen indem die SPI Transfers Atomic gemacht werden.
(Also zu Begin Interrupt deaktivieren und danach wieder Aktivieren)

Ich hoffe der Code ist halbwegs verständlich.

- Phiona

main.cpp:

Code: Alles auswählen

#include <Arduino.h>
#include "main.h"
#include <SPI.h>
#include <mcp2515.h> // https://github.com/atc1441/arduino-mcp2515
#include <PCF8574.h>
#include "conti.h"

void setup()
{

    Serial.begin(115200);

    // init port expanders
    pcf_01.begin();
    pcf_02.begin();
    pcf_03.begin();
    pcf_04.begin();
    pcf_05.begin();
    pcf_06.begin();
    
    // init each mcp2515
    for (int a = 0; a < 24; a += 1)
    {
        Serial.print("Start MCP2515 ");
        Serial.println(a, 10);
        akku[a].mcp.setBitrate(CAN_250KBPS);
        akku[a].mcp.setNormalMode();
        akku[a].mcp.reset();
    }

}

boolean light_status = 0;
uint8_t power_setting = 0;
char out_string[100];
char test;
uint32_t lastsend = 0;
uint32_t lastmsg = 0;


void loop()
{
    i2c_datasend(&pcf_03, 3, 1);
    _delay_us(100);
    i2c_datasend(&pcf_03, 3, 0);
    _delay_us(100);

    if (millis() - lastsend >= 100)
    { // Keeps the Battery alive needs to be send periodically
        lastsend = millis();
        // send keepalive to each
        for (int a = 0; a < 24; a += 1)
        {
            sendCAN(&akku[a].mcp, 0x201, 4, 0, 1, 0, 0, 0, 0, 0, 0);
        }
    }
    // check all mcp2515 for errors and new messages
    for (int a = 0; a < 24; a += 1)
    {
        if (akku[a].mcp.getErrorFlags() == 0x15)
        {   // On Can Error 0x15 restart CAN & Toggle Akku-DATA+
            Serial.println("CAN-Error 0x15, CAN-RESET & Toggle Data+");
            akku[a].mcp.reset();
            akku[a].mcp.setBitrate(CAN_250KBPS);
            akku[a].mcp.setNormalMode();
        }

        if (akku[a].mcp.readMessage(&canMsg) == MCP2515::ERROR_OK)
        {   
            if (1 == 1)
            {                              // Turn 0 into a 1 to enable debug prints
                Serial.print(canMsg.can_id, HEX); // print ID
                Serial.print("   ");
                Serial.print(canMsg.can_dlc, HEX); // print DLC
                Serial.print("   ");
                for (int i = 0; i < canMsg.can_dlc; i++)
                { // print the data
                    Serial.print(canMsg.data[i], HEX);
                    Serial.print(" ");
                }
                Serial.println();
            }
            switch (canMsg.can_id)
            {
                case 0x300:
                {
                    power_setting = canMsg.data[0];
                    if (canMsg.data[2] == 0x64)
                        light_status = 1;
                    else
                        light_status = 0;
                    break;
                }
                case 0x404:
                {
                    uint16_t voltage = ((uint16_t)canMsg.data[2] | canMsg.data[3] << 8);
                    int16_t ampere = ((uint16_t)canMsg.data[0] | canMsg.data[1] << 8);
                    uint8_t percent = canMsg.data[4];

                    sprintf(out_string, "%u%% %i Light:%i            ", percent, power_setting, light_status);
                    Serial.println(out_string);
                    if (ampere < 0)
                        sprintf(out_string, "%u,%02uV -%i,%02iA            ", voltage / 1000, (voltage % 999) / 10, abs(ampere) / 1000, (abs(ampere) % 999) / 10);
                    else
                        sprintf(out_string, "%u,%02uV %i,%02iA            ", voltage / 1000, (voltage % 999) / 10, abs(ampere) / 1000, (abs(ampere) % 999) / 10);
                    Serial.println(out_string);
                    break;
                }
            }
        }
    }
}
conti.h:

Code: Alles auswählen

#include <mcp2515.h>
#include <PCF8574.h>

PCF8574 pcf_01(0x26);
PCF8574 pcf_02(0x25);
PCF8574 pcf_03(0x24);
PCF8574 pcf_04(0x23);
PCF8574 pcf_05(0x22);
PCF8574 pcf_06(0x21);

struct can_frame canMsg;
void sendCAN(uint32_t id, uint8_t length, uint8_t data0 = 0x00, uint8_t data1 = 0x00, uint8_t data2 = 0x00, uint8_t data3 = 0x00, uint8_t data4 = 0x00, uint8_t data5 = 0x00, uint8_t data6 = 0x00, uint8_t data7 = 0x00);

int Akku_Nr = 0;

void i2c_datasend(const PCF8574 *pcf, int pin, bool state) // i2c Adresse , Pin, Low/High
{
  bool status;

  if (!(status = pcf->isConnected()))
  {
    Serial.print("Not connected ");
  }

  if (pcf->lastError())
  {
    Serial.print("I2C Fehler Adresse 0x");
    Serial.println(pcf->getAddress());
  }

  pcf->write(pin, state);
}


class MCPCONTI: public MCP2515 {

    private:

        const PCF8574 *PCF;
        int CS;

    public:

        MCPCONTI(const PCF8574 *_PCF, const uint8_t _CS) : MCP2515(_CS)
        {
            CS = _CS;
            PCF = _PCF;
            endSPI();
        }

        void startSPI() {
            SPI.beginTransaction(SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0));
            i2c_datasend(PCF, CS, 0);
        }

        void endSPI() {
            i2c_datasend(PCF, CS, 1);
            SPI.endTransaction();
        }
};

typedef struct
{
  MCPCONTI mcp;
  int toggle_pin;
  int intr_pin;
} akku_t;

akku_t akku[24] = {
    {.mcp = MCPCONTI(&pcf_01, 3), 0, 49},
    {.mcp = MCPCONTI(&pcf_01, 2), 1, 48},
    {.mcp = MCPCONTI(&pcf_01, 5), 6, 47},
    {.mcp = MCPCONTI(&pcf_01, 4), 7, 46},
    {.mcp = MCPCONTI(&pcf_02, 1), 4, 45},
    {.mcp = MCPCONTI(&pcf_02, 3), 5, 44},
    {.mcp = MCPCONTI(&pcf_02, 2), 6, 43},
    {.mcp = MCPCONTI(&pcf_02, 0), 7, 42},
    {.mcp = MCPCONTI(&pcf_03, 3), 0, 30},
    {.mcp = MCPCONTI(&pcf_03, 2), 1, 31},
    {.mcp = MCPCONTI(&pcf_03, 5), 6, 32},
    {.mcp = MCPCONTI(&pcf_03, 4), 7, 33},
    {.mcp = MCPCONTI(&pcf_04, 1), 4, 34},
    {.mcp = MCPCONTI(&pcf_04, 3), 5, 35},
    {.mcp = MCPCONTI(&pcf_04, 2), 6, 36},
    {.mcp = MCPCONTI(&pcf_04, 0), 7, 37},
    {.mcp = MCPCONTI(&pcf_05, 3), 0, 22},
    {.mcp = MCPCONTI(&pcf_05, 2), 1, 23},
    {.mcp = MCPCONTI(&pcf_05, 5), 6, 24},
    {.mcp = MCPCONTI(&pcf_05, 4), 7, 25},
    {.mcp = MCPCONTI(&pcf_06, 1), 4, 26},
    {.mcp = MCPCONTI(&pcf_06, 3), 5, 27},
    {.mcp = MCPCONTI(&pcf_06, 2), 6, 28},
    {.mcp = MCPCONTI(&pcf_06, 0), 7, 29}
    };

void sendCAN(MCPCONTI *mcp,  uint32_t id, uint8_t length, uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3, uint8_t data4, uint8_t data5, uint8_t data6, uint8_t data7)
{ 
  struct can_frame canMsg1;
  canMsg1.can_id = id;
  canMsg1.can_dlc = length;
  canMsg1.data[0] = data0;
  canMsg1.data[1] = data1;
  canMsg1.data[2] = data2;
  canMsg1.data[3] = data3;
  canMsg1.data[4] = data4;
  canMsg1.data[5] = data5;
  canMsg1.data[6] = data6;
  canMsg1.data[7] = data7;
  mcp->sendMessage(MCPCONTI::TXB1, &canMsg1);

}
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Vielen lieben Dank für deine Mühe!!!
Ich versuche das mal zu lesen und zumindest grob zu verstehen.

Lg
Boris
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Interessant:
Der code wird compiliert, mit Warnungen. Wenn ich den code hier mit drin habe, hängt die CPU direkt, lasse ich es weg läuft die CPU und sendet zumindest Serial Daten.



Code: Alles auswählen

typedef struct
{
  MCPCONTI mcp;
  int toggle_pin;
  int intr_pin;
} akku_t;

akku_t akku[24] = {
    {.mcp = MCPCONTI(&pcf_01, 3), 0, 49},
    {.mcp = MCPCONTI(&pcf_01, 2), 1, 48},
    {.mcp = MCPCONTI(&pcf_01, 5), 6, 47},
    {.mcp = MCPCONTI(&pcf_01, 4), 7, 46},
    {.mcp = MCPCONTI(&pcf_02, 1), 4, 45},
    {.mcp = MCPCONTI(&pcf_02, 3), 5, 44},
    {.mcp = MCPCONTI(&pcf_02, 2), 6, 43},
    {.mcp = MCPCONTI(&pcf_02, 0), 7, 42},
    {.mcp = MCPCONTI(&pcf_03, 3), 0, 30},
    {.mcp = MCPCONTI(&pcf_03, 2), 1, 31},
    {.mcp = MCPCONTI(&pcf_03, 5), 6, 32},
    {.mcp = MCPCONTI(&pcf_03, 4), 7, 33},
    {.mcp = MCPCONTI(&pcf_04, 1), 4, 34},
    {.mcp = MCPCONTI(&pcf_04, 3), 5, 35},
    {.mcp = MCPCONTI(&pcf_04, 2), 6, 36},
    {.mcp = MCPCONTI(&pcf_04, 0), 7, 37},
    {.mcp = MCPCONTI(&pcf_05, 3), 0, 22},
    {.mcp = MCPCONTI(&pcf_05, 2), 1, 23},
    {.mcp = MCPCONTI(&pcf_05, 5), 6, 24},
    {.mcp = MCPCONTI(&pcf_05, 4), 7, 25},
    {.mcp = MCPCONTI(&pcf_06, 1), 4, 26},
    {.mcp = MCPCONTI(&pcf_06, 3), 5, 27},
    {.mcp = MCPCONTI(&pcf_06, 2), 6, 28},
    {.mcp = MCPCONTI(&pcf_06, 0), 7, 29}
    };
*/


Fehler:

Code: Alles auswählen

mpiling .pio/build/sparkfun_megapro16MHz/libc0b/PCF8574/PCF8574.cpp.o
src/main.cpp: In function 'void i2c_datasend(const PCF8574*, int, bool)':
src/main.cpp:25:35: warning: passing 'const PCF8574' as 'this' argument discards qualifiers [-fpermissive]
   if (!(status = pcf->isConnected()))
                                   ^
In file included from src/main.cpp:4:0:
.pio/libdeps/sparkfun_megapro16MHz/PCF8574/PCF8574.h:37:11: note:   in call to 'bool PCF8574::isConnected()'
   bool    isConnected();
           ^~~~~~~~~~~
src/main.cpp:30:22: warning: passing 'const PCF8574' as 'this' argument discards qualifiers [-fpermissive]
   if (pcf->lastError())
                      ^
In file included from src/main.cpp:4:0:
.pio/libdeps/sparkfun_megapro16MHz/PCF8574/PCF8574.h:80:11: note:   in call to 'int PCF8574::lastError()'
   int     lastError();
           ^~~~~~~~~
src/main.cpp:33:36: warning: passing 'const PCF8574' as 'this' argument discards qualifiers [-fpermissive]
     Serial.println(pcf->getAddress());
                                    ^
In file included from src/main.cpp:4:0:
.pio/libdeps/sparkfun_megapro16MHz/PCF8574/PCF8574.h:43:11: note:   in call to 'uint8_t PCF8574::getAddress()'
   uint8_t getAddress();  
           ^~~~~~~~~~
src/main.cpp:36:24: warning: passing 'const PCF8574' as 'this' argument discards qualifiers [-fpermissive]
   pcf->write(pin, state);
                        ^
In file included from src/main.cpp:4:0:
.pio/libdeps/sparkfun_megapro16MHz/PCF8574/PCF8574.h:52:11: note:   in call to 'void PCF8574::write(uint8_t, uint8_t)'
   void    write(const uint8_t pin, const uint8_t value)
Benutzeravatar
Toni
Beiträge: 2523
Registriert: Di 13. Aug 2013, 18:24

Re: Der AVR-/ARDUINO-Faden

Beitrag von Toni »

Toni hat geschrieben: So 8. Jan 2023, 11:29 OK, damit sollte alles klar sein :)

Mein Probem mit dem Clock-Vorteiler ist auf der MC Seite auch explizit beschrieben:
"Reaktivieren beim CLKPR-Problem (Attiny13)
Beim Attiny13 (und anderen) kann man aus dem Programm heraus die Taktquelle mit dem Vorteilerregister CLKPR heruntersetzen. Beim nächsten ISP-Programmieren kann das zu Problemen führen, wenn das Programm anläuft, die Taktquelle sehr langsam schaltet und dann erst in den ISP-Programmiermodus geschaltet wird. Travel Rec. beschreibt wie man mit einem Pull-Down-Widerstand an RESET Anlaufen des problematischen Programms verhindert [1]
."
Muss man halt wissen dass es so ist. Für mich ließ sich das lösen, indem ich nochmal ein Bootloader aufgebraten hatte, und den Vorteiler vermied.

Beim fehlerhaften Brennen des Bootloaders wurden vermutlich Fuses verpfuscht, da krame ich mal nach einem externen Quarzoszillator.

...dann versuche ich demnächst mal vorsichtig über AVRDUDE harmlose Fuses zu ändern.

Danke euch :D
Ich wollte dazu noch eine Rückmeldung geben:
Bastelbruder hat geschrieben: So 8. Jan 2023, 01:04 Wenn so ein Controller "verfust" ist, bedeutet das im Allgemeinen daß die Takterzeugung nicht mehr läuft. Und ohne Takt gehts nicht. Aber es gibt da einen Trick, ein Kollege hat die Zusatzschaltung Defi genannt. :D Ein Oszillator mit mindestens 100 kHz, der mit 100 pF an den Takteingang gekoppelt wird. Das darf ein Oszillator im DIL-Gehäuse sein oder auch ein 555 mit Minimalbeschaltung.
Das funktioniert! Ich habe jetzt standardmäßig einen Quarzoszillator mit C=470pF in Reihe am Programmieradapter, der bei Bedarf an den CLKI-Pin gejumpert werden kann.

Der Burn-O-Mat funktionierte bei mir nicht mit Ubuntu, dafür aber der AVRDUDESS über MONO. Ich kann Fuses auslesen und beschreiben. Testweises Verstellen der CKSEL-Fuses führte auch prompt dazu, dass der Tiny nicht mehr ansprechbar war, auch nicht mit externer Taktquelle. Mit dem Defi war das aber rückgängig zu machen???
War ein externes Problem: mit C=100nF direkt an den Versorgungspins funktionierte es auch mit dem externen Takt.

Noch ein Hinweis: wenn über CKSEL 128kHz intern eingestellt wird, muss zum Ansprechen mit AVRDUDE die Datenrate stark runtergedreht werden. 16kHz funktioniert.

Die gesammelten verfusten Tinys konnte ich zurücksetzen :D
ch_ris
Beiträge: 3029
Registriert: Mo 30. Nov 2015, 10:08

Re: Der AVR-/ARDUINO-Faden

Beitrag von ch_ris »

der burn mat unter linux...irgendwas war da, habs vergessen wie ich das hingekriegt hab. man könnte ihn mal per konsole starten bei Interesse.
Benutzeravatar
Toni
Beiträge: 2523
Registriert: Di 13. Aug 2013, 18:24

Re: Der AVR-/ARDUINO-Faden

Beitrag von Toni »

starten ging, aber der ProgAdapter (USBasp) war nicht erreichbar. Mit AVRDUDESS lief es auf Anhieb
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Sehr seltsam das der MC abkackt, wenn ich das hier hochlade.


akku_t akku[24] = {
{.mcp = MCPCONTI(&pcf_01, 3), 0, 49},



Ich habe diesen Abschnitt für die PCF Lib gefunden

Code: Alles auswählen

bool setAddress(const uint8_t deviceAddress) sets the device address after construction. 
Can be used to switch between PCF8574 modules runtime. Note this corrupts internal buffered values, so one might need to call read8() and/or write8(). 
Returns true if address can be found on I2C bus.
Das müsste ja bedeuten, ich kann auf verschiedenen PCFs herumschreiben, ohne das die neu initialisiert werden, so wie ich das beim ersten mal gemacht hatte.
Also einen nur einen Constructor für die PCF und dann nur die Adressen umbiegen.
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Also das mit den Klassen....
klappt nicht. Ich muss das mal an einem Testprogramm versuchen.

Mal hierzu,

Code: Alles auswählen

class HighTechMCP2515 : public MCP2515 {

void startSPI() {
	SPIn->beginTransaction(SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0));
	i2c_datasend(..., 3, 0);
	}

	void endSPI() {
	i2c_datasend(..., 3, 1);
	SPIn->endTransaction();
}
}
Wenn ich das richtig verstanden habe, kann ich damit zwar mit
HighTechMCP2515 htmcp2515;

htmcp2515.startSPI
die neue Funktion benutzen, und die MCP2515 Funktion startSPI wird überschrieben, aber wenn von der MCP2515 Klasse eine Funktion die Funktion startSPI aufruft, wird wieder die original Funktion benutzt oder?
Benutzeravatar
ProgBernie
Beiträge: 584
Registriert: Fr 16. Sep 2022, 21:59
Wohnort: Zwischen Hamburg und Haiti ^W Lübeck

Re: Der AVR-/ARDUINO-Faden

Beitrag von ProgBernie »

Hightech hat geschrieben: Fr 13. Jan 2023, 20:29
[überladene Methode]

Wenn ich das richtig verstanden habe, kann ich damit zwar mit
HighTechMCP2515 htmcp2515;

htmcp2515.startSPI
die neue Funktion benutzen, und die MCP2515 Funktion startSPI wird überschrieben, aber wenn von der MCP2515 Klasse eine Funktion die Funktion startSPI aufruft, wird wieder die original Funktion benutzt oder?
Ich habe mir gerade den Sourcecode von MCP2515 angesehen. Du hast Recht, die Klasse ist nicht darauf vorbereitet abgeleitet zu werden, dazu müssten die Methoden virtual sein. Eine der vielen Fallgruben in C++.
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Ich geb auf. Da bin ich ja 2525 noch dran.
Also fädel ich jetzt um, der CS kommt hart an den Arduino, der INT dann halt über den PCF. Den Int brauche ich nicht so dringend.
Benutzeravatar
Weisskeinen
Beiträge: 3942
Registriert: Di 27. Aug 2013, 16:19

Re: Der AVR-/ARDUINO-Faden

Beitrag von Weisskeinen »

Andere Library nehmen oder Library ganz verschrotten und zu Fuß programmieren geht nicht?
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Ich denke, bei 24 Akkus die gleichzeitig wild herum senden wird es echt wahnsinnig kniffelig, die dann per SPI und I2C gleichzeitig zu verhackstücken.
Zudem hab ich schon bei 4 Akkus gleichzeitig schon Probleme, die korrekt zu initialisieren. Ich muss die ja per Hardware-Toggle aufwecken, schauen das die auch laufen, wenn nicht dann nochmal wecken, timeout, wenn es zu lange dauert, timeout-counter das es nicht für immer hängen bleibt......

So komme ich dann zur Einsicht, das ich wohl je Akku einen MC nehme und den dann schlicht Modbus-RTU sprechen lasse.

Ich kenn da jemand der so ModBus macht, allerdings aufm STM und nicht auf AVR, aber vielleicht kann ich den ja überreden, mir was schickes kleines in Modbus zu frickeln.
Jannyboy
Beiträge: 1406
Registriert: So 11. Aug 2013, 14:49
Wohnort: Kreis Augsburg

Re: Der AVR-/ARDUINO-Faden

Beitrag von Jannyboy »

Hightech hat geschrieben: Di 17. Jan 2023, 20:13 Ich denke, bei 24 Akkus die gleichzeitig wild herum senden wird es echt wahnsinnig kniffelig,
CAN-Bus ist doch genau dafür gemacht.
Daher verstehe ich nicht warum die Verrenkungen mit den einzelnen CAN-Bausteine und Port-Expandern.
Ich Auto quatschen auch zig Steuergeräte via CAN und es gibt kaum Kollisionen.

Grüße Jan
Benutzeravatar
sukram
Beiträge: 3063
Registriert: Sa 10. Mär 2018, 18:27
Wohnort: Leibzsch

Re: Der AVR-/ARDUINO-Faden

Beitrag von sukram »

Weil die Akkus blöd wie 10m Feldweg sind und alle auf die gleiche Adresse ansprechem...
Benutzeravatar
Fritzler
Beiträge: 12578
Registriert: So 11. Aug 2013, 19:42
Wohnort: D:/Berlin/Adlershof/Technologiepark
Kontaktdaten:

Re: Der AVR-/ARDUINO-Faden

Beitrag von Fritzler »

Hightech hat geschrieben: Di 17. Jan 2023, 20:13 Ich kenn da jemand der so ModBus macht, allerdings aufm STM und nicht auf AVR, aber vielleicht kann ich den ja überreden, mir was schickes kleines in Modbus zu frickeln.
Ich?
Modbus hatte ich zuerst aufm AVR geshrieben und dann auf STM32 portiert und dann gleichzeitig nach C++ für eine bessere Abstraktion zwischen Modbus Logik und UART HW-
Hier die alte AVR Grütze im Anhang, angaben ohne Gewehr.

Neue Grütze:
https://git.fritzler-avr.de/fritzler/modbus-slave
Dateianhänge
mb_remotemode.h
(868 Bytes) 19-mal heruntergeladen
mb_remotemode.c
(4.32 KiB) 18-mal heruntergeladen
mb_process.h
(312 Bytes) 17-mal heruntergeladen
mb_process.c
(9.22 KiB) 17-mal heruntergeladen
mb_menu.h
(1.34 KiB) 18-mal heruntergeladen
mb_menu.c
(7.19 KiB) 18-mal heruntergeladen
mb_defs.h
(1.27 KiB) 17-mal heruntergeladen
mb_crc.h
(448 Bytes) 18-mal heruntergeladen
mb_crc.c
(1.34 KiB) 18-mal heruntergeladen
mb_callbacks.h
(392 Bytes) 18-mal heruntergeladen
mb_callbacks.c
(3.07 KiB) 20-mal heruntergeladen
Kenakapheus
Beiträge: 173
Registriert: Fr 1. Jan 2016, 20:43
Wohnort: Freie Feldlage (Ja, da wo das Treffen ist))

Re: Der AVR-/ARDUINO-Faden

Beitrag von Kenakapheus »

Ich kann sonst auch das hier sehr Empfehlen:

https://github.com/mbs38/yaMBSiavr

Das geht allerdings von komplett Baremetal aus.
Benutzeravatar
sukram
Beiträge: 3063
Registriert: Sa 10. Mär 2018, 18:27
Wohnort: Leibzsch

Re: Der AVR-/ARDUINO-Faden

Beitrag von sukram »

Kenakapheus hat geschrieben: Di 17. Jan 2023, 21:38 Ich kann sonst auch das hier sehr Empfehlen:

https://github.com/mbs38/yaMBSiavr

Das geht allerdings von komplett Baremetal aus.
Darauf aufbauend habe ich meine 1Wire - Modbus Adapter gebaut. Die funktionieren mittlerweile sehr zufriedenstellend. Das wollte ich mal noch etwas "schön machen" (Race Conditions und RAM Verschwendung entfernen und den I2C BME280 non-blocking einbinden...) und dann hier vorstellen. Momentan sieht der Code nach Frankensteins Monster aus. Aus 3 oder 4 Quellen zusammengeklaut (1W von uCnet, Modbus von yaMBSiavr, BME von Bosch & Fritzler...) und mit heißer Nadel zusammengestrickt.
Benutzeravatar
ProgBernie
Beiträge: 584
Registriert: Fr 16. Sep 2022, 21:59
Wohnort: Zwischen Hamburg und Haiti ^W Lübeck

Re: Der AVR-/ARDUINO-Faden

Beitrag von ProgBernie »

Jannyboy hat geschrieben: Di 17. Jan 2023, 20:30 Ich Auto quatschen auch zig Steuergeräte via CAN und es gibt kaum Kollisionen.
Das geht nur weil jede blöde Birne in dem Käfig einen eigenen speziellen Controller hat der die Frames mit eindeutigen Inhalten verhackstückt. Es gibt bei CAN ja keine adressierbaren Komponenten, lediglich Nachrichtentypen. Hätte nicht wirklich jedes Teil einen eigenen Controller würde es Dir überhaupt nichts nützen wenn da sowas wie "Birne defekt" auf dem Bus ankommt. Man weiss ja nicht welche. So ist das auch bei den Akkus, die senden alle brav ihre Nachricht "Akkuspannung 39.75V", aber man hat dann keinen Schimmer von welchem Akku das kommt. Das Conti-System war ja nie dafür gemacht mehr als einen Akku am Rad spazieren zu fahren.
Ka6Pilot
Beiträge: 10
Registriert: Mi 29. Jan 2020, 22:43

Attiny 412 (tinyAVR) SPI ausschalten

Beitrag von Ka6Pilot »

Hallo in die Runde,

ich bin gerade dabei, mit einem Attiny 412 und einem MAX31855 herumzuexperimentieren. Der Attiny412 soll dabei regelmäßig den MAX31855 mit Strom versorgen und prüfen, ob sich der (TC+)-Pin (SENSE) mit einem Pull-Up-Widerstand auf HIGH ziehen lässt. Wenn das nicht der Fall ist, wird eine Messung gestartet. Anschließend wird die Stromversorgung zum MAX31855 wieder unterbrochen und die SCK- und CS-Leitung werden als INPUT definiert, um den MAX31855 nicht darüber mit Strom zu versorgen.
Später soll ein µC mit mehr Pins zum Einsatz kommen und das Messergebnis auf eine SD-Karte geschrieben werden.
Nun zum Problem: Initiiert man den MAX31855 mit Software-SPI, funktioniert der Aufbau problemlos (Bild 1; Gelb: SCK; Blau: SO). Mit Hardware-SPI kommt bei ansonsten unverändertem Code überhaupt keine Übertragung zustande (Bild 2). Lässt man in Zeile 38 in dem anghängten Code das

Code: Alles auswählen

pinMode(2, OUTPUT); 
weg, funktioniert die Übertragung gelegentlich (Bild 3).
Gibt es eine Möglichkeit, das Hardware-SPI zu verwenden und die entspechenden Pins bei Nichtgebrauch hochohmig zu schalten?
Viele Grüße

Untenstehend ist der Programmcode, im Anhang drei Oszillogramme sowie der Schaltplan.

Code: Alles auswählen

/*
* ATTINY412  Pinout Convention: 
 *               ______
 *          VCC-|1    8|-GND
 * D0 PA6(TX)---|2    7|-PA3(SCK)  D4
 * D1 PA7(RX)---|3    6|-PA0(UPDI) D5
 * D2 PA1(MOSI)-|4____5|-PA2(MISO) D3
 */
 
#include <SPI.h>
#include <avr/sleep.h>
#include "Adafruit_MAX31855.h"

#define MAXDO   3     // software SPI
#define MAXCLK  4     // software SPI

#define MAXCS   2     // ADC Chip Select  
int VADC  = 1;        // ADC Power Supply
int SENSE = 0;        // ADC TC+ Input

Adafruit_MAX31855 thermocouple(MAXCLK, MAXCS, MAXDO); // software SPI
//Adafruit_MAX31855 thermocouple(MAXCS); // hardware SPI

void setup() {
  thermocouple.begin();
  RTC_init();                           // Initialize RTC 
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // Set sleep mode to POWER DOWN mode 
  sleep_enable();                       // Enable sleep mode, but not going to sleep yet
  pinMode(VADC, OUTPUT);                // ADC Power Supply   
}

void loop() {
  digitalWrite(VADC, HIGH);             // Power on ADC
  pinMode(SENSE, INPUT_PULLUP);         // Check if Thermocouple is connected
  delay(2);                             // Time constant with 10n between TC+ and TC- is about .5 ms
  if (digitalRead(SENSE)== LOW) {       // If TC is connected
    pinMode(SENSE, INPUT);              // sense pin floating
    pinMode(2, OUTPUT);                 // ADC CS Pin
    pinMode(4, OUTPUT);                 // ADC SCK Pin 
    delay(98);                          // First valid Data will be available 200 ms after Power-Up                   
    thermocouple.readCelsius();
    delay(1);  
    pinMode(2, INPUT);                  // deactivate ADC CS Pin 
    pinMode(4, INPUT);                  // deactivate ADC SCK Pin
  }
  digitalWrite(VADC, LOW);              // Power down ADC
  pinMode(SENSE, INPUT);                // sense pin floating
  sleep_cpu();  
}

void RTC_init(void)
{
  while (RTC.STATUS > 0);               // Wait for Synchronization
  RTC.CLKSEL = RTC_CLKSEL_INT32K_gc;    // 32.768kHz Internal Ultra-Low-Power Oscillator (OSCULP32K) 
  RTC.PITINTCTRL = RTC_PI_bm;           // PIT Interrupt: enabled 
  RTC.PITCTRLA = RTC_PERIOD_CYC16384_gc | RTC_PITEN_bm;  // RTC Clock Cycles 16384 | Enable PIT counter
}
    
ISR(RTC_PIT_vect)
{
  RTC.PITINTFLAGS = RTC_PI_bm;          // Clear interrupt flag 
}
Dateianhänge
MAX31855.png
Bild 2.png
Bild 3.png
Bild 1.png
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

MCP2515 Interruptfragen, komme nicht weiter :(

Beitrag von Hightech »

Moin zusammen,
ich versuche gerade den MCP2515 dazu zu bringen, nur auf die Can-Message mit der ID 0x404 zu reagieren und den Interrupt-Pin zu setzen.
Dann möchte ich nur diese eine Message lesen.

Leider wird der Interrupt immer ausgelöst, egal welche ID, auch wenn ich eine ID angebe, die es nicht gibt.

Im Setup setze ich
MCP2515(cspin).setConfigMode()
MCP2515(cspin).setFilterMask(MCP2515::MASK0, false,0x7FF)
MCP2515(cspin).setFilte(MCP2515::RXF0, false,0x404)
MCP2515(cspin).setNormalMode()

Leider kommt der Interrupt immer, und es sind auch alle Messages im RX Puffer.

Eigenlich sollte nach dem Lesen der Interrupt auch wieder automatisch zurück gesetzt werden.

Was mache ich da falsch?

Die MCP2515 LIb ist jene, die ich auch in dem Conti-Faden nutze.

Ist der Wir vielleicht der RX Overflow-Interrupt immer gesetzt, Muss ich das extra ausschalten?

Empfängt der MCP2515 im Interruptmodus weiter Messages und überschreibt den Puffer, oder wartet der, bis der Puffer geleert ist.
Das kann man wohl einstellen, das der RX Puffer überschrieben wird. Ist aber aus, soweit ich das verstanden habe.

Oder ist hier die Lösung beschrieben?
On taking an MCP2515 interrupt, the first thing we do is to disable interrupts from that chip in the interrupt controller. Then read canintf, eflg and canstat2 in the one three-byte read..
If either (or both) RX Interrupts are set we service them, ELSE if a transmit interrupt is set we service it, ELSE if an error interrupt is set we service it. Then the interrupts are enabled and the routine returns. It does NOT try to service more than "one event per customer". as we've got three of them to handle in rotation and don't want a long service on one starving the other two.
The interrupt flags are cleared in the status register with the "Bit Modify" instruction, only clearing the status that has just been serviced.
virtexultra
Beiträge: 127
Registriert: So 9. Dez 2018, 11:30

Re: Attiny 412 (tinyAVR) SPI ausschalten

Beitrag von virtexultra »

Ka6Pilot hat geschrieben: Sa 21. Jan 2023, 17:24 ich bin gerade dabei, mit einem Attiny 412 und einem MAX31855 herumzuexperimentieren.
Mal etwas ins blaue geraten:

schaue dir mal das SSD Bit im CTRLB Register an. Ich könnte mir vorstellen das die SPI Periph in den Slave Modus schaltet, wenn CS im Input Modus ist und extern irgendwie low wird. Überprüfbar sollte das per CTRLA.MASTER sein.

Ich würde mir wegen dem Leakage Current des SPI Interfaces weniger Sorgen machen - 1µA max. pro Pin ist ja nicht wirklich viel.

Du könntest einen Pin sparen wenn du das OC Bit des MAX31855 auswertest um zu prüfen ob ein TC angeschlossen ist.

Auf den Oszillogrammen kann ich nicht wirklich etwas erkennen. CS? sieht auf Bild2 deutlich länger aus als auf Bild 3/1.
ch_ris
Beiträge: 3029
Registriert: Mo 30. Nov 2015, 10:08

Re: Der AVR-/ARDUINO-Faden

Beitrag von ch_ris »

Code: Alles auswählen

bool checkTTL() {
	pinMode(pinTX, INPUT_PULLUP);
	pinMode(pinRX, INPUT_PULLUP);
	delay(10);
	return (digitalRead(pinTX) && digitalRead(pinRX) ); 
}
Die Methode soll entscheiden ob Serial gestartet wird oder nicht.
Bei einem Tiny85. Die Pins sind die Komparator Pins, die sollen dann was richtiges machen wenn kein Adapter angesteckt ist.
Adapter ohne VCC, der Tiny kriegt seinen Strom extern.
Frage: zieht der stromlose TTL Adapter, ohne Computer dran, RX und/oder TX auf low?
Bei dem Schaltplan von meinem, bzw. von dem den ich grade hab, sieht es so aus,
da sind 3 Dioden in Reihe gegen GND. Bei 5v sollte das doch reichen für low. messe ich nach.
Aber: ist das so üblich oder könnte mir ein anderer Adapter ein Strich durch die Rechnung machen?
Bumbum
Beiträge: 280
Registriert: Mi 22. Apr 2015, 19:04

Re: Der AVR-/ARDUINO-Faden

Beitrag von Bumbum »

Hallo,

ich habe mir SG90 Servos bestellt und wollte diese gerade mit einem Arduino verheiraten. Allerdings klappt es nicht so wie erwartet. Die Servos "ticken" nur, wenn der Arduino ein PWM-Signal ausgibt. Laut Google soll das die Spannungsversorgung sein. Hier bin ich aber sicher alles richtig gemacht zu haben. Der Arduino wird per USB vom PC versorgt. Zum Servo wird nur GND und das PWM-Signal geführt. Der Servo selbst hängt an meinem Labornetzteil an 5V mit einer Strombegrenzung bei 1,5 A, die aber nie erreicht wird. Als PWM-Ausgang am Arduino Nano haben schon Pin 8 bis 10 getestet, überall das gleiche.

Ein Befehl den Servo an eine Position zu fahren hat keinen Effekt. Wenn ich den Servo aber von Hand bewege gibt es eine Position, bei der er nicht mehr tickt. Ab dann kann ich den Servo auch mit dem Arduino steuern.

Um diese Theorie zu beweisen, habe ich beim Start des Arduino eine Routine, die langsam alle Positionen des Servos "abfährt". Der Servo tickt, bis die richtige Position erreicht ist und fährt ab dann brav mit.

Das Labornetzteil halte ich für Potent genug. Aber ich habe zum Testen auch schon mal 220µF direkt an die Versorgung des Servo gelötet. Leider ohne Erfolg.

Wer hat eine Idee, was hier die Ursache sein könnte? Zur Belustigung ein Foto meines Versuchsaufbaus:
Servo Test.jpg
von oben kommt rot + schwarz die Versorgung vom Netzteil. Bei der grünen Leitung habe ich versuchsweise das Poti im Servo angezapt, weil mich die Werte interessiert haben. Aber auch ohne diese Verbindung habe ich das Problem.

Viele Grüße
Andreas
Benutzeravatar
Bastelbruder
Beiträge: 11481
Registriert: Mi 14. Aug 2013, 18:28

Re: Der AVR-/ARDUINO-Faden

Beitrag von Bastelbruder »

iIch könnte mir hier ein Masseproblem vorstellen. Gleichstrom? Das Servo zieht steilflankige Impulsströme aus der Versorgung, die nicht nur auf dem roten Draht zu Spannungsabfall bipolaren Spannungsimpulsen führen.
Masse bedeutet: absolut identisches Potenzial. Auch die Versorgungsspannung könnte "abgeblockt" sein, so etwa mit hundert Mikrofarad (mindestens) am Servostecker. Ich sehe hier lauter Induktivitäten, die womöglich mit Eisendraht gewickelt sind.

Früher - zu Heinz Richters Zeiten - hat das noch funktioniert. Heute sind nirgends mehr bipolare Transistoren in den ICs sondern CMOS mit Schutzdioden die die ordentliche Funktion gern unterwandern wenn man sie auch unbeabsichtigt mit Arbeit überhäuft.

Ich durfte kürzlich eine aus Maker-Zubehör zusdammengestückelte Schaltung begutachten, da ist bloß so ein Infrarot-Fernsteuerempfänger immer wieder Amok gelaufen und hat Dauersignal selber erzeugt. Weil der hundert Nano-Kondensator aus dem Datenblatt bloß 10 cm Flachstrippe und einen Steckverbinder vom Empfangs-Chip entfernt war.

Das IC von damals hab ich doch schon vor langer Zeit hier erwähnt.
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Ich glaub ich habe mich verklassifiziert, irgendwie komisch, oder ist das so korrekt?


Main.cpp

Code: Alles auswählen

#include <Arduino.h>
#include <EEPROM.h>
#include <Wire.h>
#include "akku.h"

typedef struct
{
  AKKU akku;
  int i2c_addr;
} akku_t;

akku_t DerAkku[6] = {
    {.akku = AKKU(31), 31},
    {.akku = AKKU(32), 32},
    {.akku = AKKU(33), 33},
    {.akku = AKKU(34), 34},
    {.akku = AKKU(35), 35},
    {.akku = AKKU(36), 36}

};

void setup()
{
  Wire.begin();
  Serial.begin(115200);
}

void loop()
{
delay(10);
  for (int a = 0; a < 6; a++)
  {

    DerAkku[a].akku.read(DerAkku[a].i2c_addr);
    if (!(DerAkku[a].akku.power_fail < 0 || DerAkku[a].akku.power_fail == 255))
    {
      Serial.print(" A: ");
      Serial.print(a);
      Serial.print(" fail: ");      
      Serial.print(DerAkku[a].akku.fail);
      Serial.print(" Pwr: ");
      Serial.print(DerAkku[a].akku.power_fail);
      Serial.print(" Ser: ");
      for (int b = 0; b < 8; b++)
      {
        Serial.print(DerAkku[a].akku.serial[b], HEX);
        Serial.print(" ");
      }
      Wire.beginTransmission(DerAkku[a].i2c_addr);
      Wire.write(DerAkku[a].akku.command);
      Wire.endTransmission();
      sprintf(DerAkku[a].akku.out_string, " %03u%%  ", DerAkku[a].akku.percent);
      Serial.print(DerAkku[a].akku.out_string);
      if (DerAkku[a].akku.ampere < 0)
        sprintf(DerAkku[a].akku.out_string, "%u,%02uV -%i,%02iA ", DerAkku[a].akku.voltage / 1000, (DerAkku[a].akku.voltage % 999) / 10, abs(DerAkku[a].akku.ampere) / 1000, (abs(DerAkku[a].akku.ampere) % 999) / 10);
      else
        sprintf(DerAkku[a].akku.out_string, "%u,%02uV %02i,%02iA ", DerAkku[a].akku.voltage / 1000, (DerAkku[a].akku.voltage % 999) / 10, abs(DerAkku[a].akku.ampere) / 1000, (abs(DerAkku[a].akku.ampere) % 999) / 10);
      Serial.println(DerAkku[a].akku.out_string);
     DerAkku[a].akku.command = 1;
    }
    delay(1000);
  }
}
akku.h

Code: Alles auswählen

#ifndef _AKKU_H_
#define _AKKU_H_

#include <Wire.h>

class AKKU
{
private:
    int i2c_addr;
public:
    int command;
    uint16_t voltage;
    int power_fail;
    int16_t ampere;
    uint8_t percent;
    char out_string[100];
    int serial[8];
    int fail;
    AKKU(int _AD);
    void read(int i2c_addr);
};

#endif

akku.cpp

Code: Alles auswählen

#include "akku.h"
#include <Arduino.h>

AKKU::AKKU(int _AD){
    i2c_addr=_AD;
    Wire.begin(i2c_addr);
}

    void AKKU::read(int ic2_addr)
    {   
       
        byte a, b;
        Wire.requestFrom(ic2_addr, 15);// 16 Byte empfangen
        percent = Wire.read(); //0
        b = Wire.read();//1
        a = Wire.read();//2
        ampere = a;
        ampere = ampere << 8 | b;
        b = Wire.read();//3
        a = Wire.read();//4        
        voltage = a;
        voltage = voltage << 8 | b;        
        power_fail = Wire.read();//5
        //Serial.print("Power: ");
        //Serial.print(power_fail);
        //Serial.print(" Serial: ");
        for (int a = 0; a < 8; a++)
        {
            serial[a] = Wire.read();//6-13
          //  Serial.print(serial[a], HEX);
          //  Serial.print(" ");
        }
        
       fail = Wire.read();//14
    }
virtexultra
Beiträge: 127
Registriert: So 9. Dez 2018, 11:30

Re: Der AVR-/ARDUINO-Faden

Beitrag von virtexultra »

Hightech hat geschrieben: Sa 18. Feb 2023, 17:49 Ich glaub ich habe mich verklassifiziert, irgendwie komisch, oder ist das so korrekt?
Folgene Dinge sind mir aufgefallen:

Du schleppst die i2c Addr. noch mal extra in einem Strukt mit, obwohl du diese im Konstruktor übergeben hast. Ich vermute weil du es später für Wire.beginTransmission benötigst. Würde ich eine Getter Funktion schreiben und diese Information nur in der Klasse Akku speichern (oder wie später genannt komplett in die Klasse verlagern)

Code: Alles auswählen

if (!(DerAkku[a].akku.power_fail < 0 || DerAkku[a].akku.power_fail == 255))
ist für mich Code der zur Auswertung des Akkus gehört und somit auch in die dazugehörige Klasse. Also z.B. eine Klassenfunktion .powerFail() die dann die Variable power_fail überprüft. Hier passt aber auch was mit den Datentypen nicht. Wire.read() sollte ein Byte zurückliefern - vermutlich ist das als uint8_t definiert und wird somit nie < 0.

Ein Flag / Zeitstempel das überprüft ob/wann der Akku schon/das letzte Mal ausgelesen wurde. Nicht das irgendwer Akku::read erst nach dem Überprüfen eines Zustandes aufruft.

Warum das I2C Read in die Klasse integrieren und das Schreiben aber nicht? Falls die Logik mit den verschiedenen Schreibcommands ausartet kann man ja auch ::write(uint8_t cmd) als Funktion der Klasse einbauen. Es scheint auch nur das command "1" zu geben, also kann der Wert auch in den Konstruktor der Klasse.

Ich frage mich was in der ersten Runde für ein cmd an den Akku gesendet wird. Wenn du Glück hast wird der Speicher in dem die Klasse später liegt mit 0 geinit, ansonsten könnte das alles sein.

Das sind jetzt aber alles keine wirklich entscheidenden Sachen und ich sehe bis aus den letzten Punkt nichts funktionsentscheidendes.
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Danke schon man,
das command ist erst ein mal nur die Freigabe das der Akku starten soll, ist command 0, dann sendet der client keine Can-Nachichten an den Akku, dann geht die Spannung dort aus.
Besser wäre dann sicher akku.power_off() / akku.power_on()
ch_ris
Beiträge: 3029
Registriert: Mo 30. Nov 2015, 10:08

Re: Der AVR-/ARDUINO-Faden

Beitrag von ch_ris »

Wire.begin im Akku Konstruktor verstehe ich nicht.
Ist das ein Singleton oder sollte spätestens jetzt einer sein? oder egal?
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Wer es noch nicht weiß:
Einen Arduino kann man auch über das Netzwerk flashen, wenn man es über USB/Bootloader tut.
Einfach einen Raspi ans Netzwerk, über USB den Arduino dran und vom Hauptrechner dann über usbip den Arduino bedienen.

https://www.net-usb.com/de/usb-over-ip-raspberry-pi/
Bumbum
Beiträge: 280
Registriert: Mi 22. Apr 2015, 19:04

Re: Der AVR-/ARDUINO-Faden

Beitrag von Bumbum »

Hallo,

ich würde gerne ein größeres Arduino-Projekt zur besseren Übersicht in mehrere Dateien aufteilen. Aber ich bekomme es nicht hin. Hier ein kleines Beispiel für meinen Test-Sketch:

Code: Alles auswählen

#include <TFT_eSPI.h>

TFT_eSPI display = TFT_eSPI ();

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}
Dann habe ich eine Datei "Display.c" zum Projekt hinzugefügt:

Code: Alles auswählen

#include <TFT_eSPI.h>

extern TFT_eSPI display = TFT_eSPI ();
Die Datei wird mir in der Arduino IDE oben in den Tabs angezeigt. Aber das compilieren klappt mit diesem kleinen Beispiel nicht. In der Zeile:

Code: Alles auswählen

extern TFT_eSPI display = TFT_eSPI ();
erhalte ich die Fehlermeldung "Fehler: unknown type name 'TFT_eSPI'"

Wie macht man es richtig?

Viele Grüße
Andreas
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Oh,
da fehlen die Grundlegegenden Basics der Programmierung.

Da müssen wir ganz unten anfangen.
Man kann Funktionen und Klassen in Dateien auslagern. Dazu muss man aber auch die Unterschiede kennen und wie man Funktionen und Klassen benutzt und schreibt.

Vielleicht wäre ein Anfänger Tutorial zur Arduino programmierung gut.
Bumbum
Beiträge: 280
Registriert: Mi 22. Apr 2015, 19:04

Re: Der AVR-/ARDUINO-Faden

Beitrag von Bumbum »

Hallo Hightech,

ich habe die Ursache in der Zwischenzeit herausgefunden: Die Datei darf nicht die Endung .c haben, sonder muss .ino heißen.

Viele Grüße
Andreas
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Bumbum hat geschrieben: Mi 22. Mär 2023, 21:44 Hallo Hightech,

ich habe die Ursache in der Zwischenzeit herausgefunden: Die Datei darf nicht die Endung .c haben, sonder muss .ino heißen.

Viele Grüße
Andreas
Wie ? ist ja mal seltsam. Komische Sachen gibt es. Schön das es geklappt hat.
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

ESP32 low Power wakeup

Beitrag von Hightech »

Moin, wie sogt man sinnvollerweise bei einem ESP32 dafür, das der regelmäßig und zuverlässig aufwacht um zu arbeiten und dann wieder schlafen zu legen.
Dabei soll er im Schlaf wenig Strom verbrauchen.
Beim Atmel gibt es ja meistens einen unabhängigen Zähler mit externem Quarz für diesen Zweck.
Hat hier jemand sowas mit dem ESP32 gemacht?
MSG
Beiträge: 2182
Registriert: Fr 9. Nov 2018, 23:24
Wohnort: Nähe Dieburg

Re: Der AVR-/ARDUINO-Faden

Beitrag von MSG »

Andreas Spiess hatte da ein gutes Video dazu gemacht

https://youtu.be/JFDiqPHw3Vc

Im Moment laufen meine Esp32 alle ohne Schlaf
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Gibts es das auch ohne YT, ich mag keine Erklärvideos.
Die kann man nicht querlesen.....
berferd
Beiträge: 1327
Registriert: Mi 3. Apr 2019, 23:45

Re: Der AVR-/ARDUINO-Faden

Beitrag von berferd »

Anderes Thema: obacht beim Arduino Pro Mini, möglicherweise auch bei anderen: die Dinger brauchen 2-3 Sekunden bis sie an der ersten Zeile Code ankommen. Ursache ist laut Netzrecherche der Bootloader, vermute das ist die Zeit die einem das Eingreifen zum Flashen über die serielle Schnittstelle erlaubt. Kann man natürlich wieder irgendwie umflashen usw, zerstört aber den Charme des "Projekt mal schnell eben" (für Ernsthafteres macht man ja ohnehin eigene eigene Platine mit ICSP-Stecker).
MSG
Beiträge: 2182
Registriert: Fr 9. Nov 2018, 23:24
Wohnort: Nähe Dieburg

Re: Der AVR-/ARDUINO-Faden

Beitrag von MSG »

Hightech hat geschrieben: So 9. Apr 2023, 20:06 Gibts es das auch ohne YT, ich mag keine Erklärvideos.
Die kann man nicht querlesen.....
Die vom Andreas sind eigentlich ganz gut zum drüber schauen.

Ansonsten findest du hier noch ein paar Infos

https://smarthome-blogger.de/blog/esp32 ... deep-sleep

https://www.azdelivery.de/blogs/azdeliv ... tzenklappe
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Danke für die Links!
IPv6
Beiträge: 2166
Registriert: Fr 17. Mär 2017, 22:05

Re: Der AVR-/ARDUINO-Faden

Beitrag von IPv6 »

berferd hat geschrieben: So 9. Apr 2023, 20:13 Anderes Thema: obacht beim Arduino Pro Mini, möglicherweise auch bei anderen: die Dinger brauchen 2-3 Sekunden bis sie an der ersten Zeile Code ankommen. Ursache ist laut Netzrecherche der Bootloader, vermute das ist die Zeit die einem das Eingreifen zum Flashen über die serielle Schnittstelle erlaubt. Kann man natürlich wieder irgendwie umflashen usw, zerstört aber den Charme des "Projekt mal schnell eben" (für Ernsthafteres macht man ja ohnehin eigene eigene Platine mit ICSP-Stecker).
Du könntest auch einfach alle deine Arduino Pro Minis (oder Nanos oder oder oder) mit dem Optiboot Bootloader flashen, dauert nur ein paar Sekunden und hat anschließend keine Wartezeit beim starten mehr. Ist aber trotzdem weiterhin über die serielle Schnittstelle flashbar.
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Nochmal deep-Sleep Thema

Beitrag von Hightech »

Es scheint ja Probleme mit dem Deep-Sleep Modus zu geben, das der manchmal nicht wieder aufwacht.
So meine Idee jetzt :

Nach getaner Arbeit die Schaltung über einen Impuls in den Zustand "Aus" bringen. Dann wird ein Kondensator geladen.
Wenn der Kondensator weit genug geladen ist schaltet ein Fet der an diesem Kondensator hängt, die Schaltung wieder ein
So 1MOhm an 1000µF.
Wären 5µA Standby Strom

Macht das irgendwie Sinn?
Bumbum
Beiträge: 280
Registriert: Mi 22. Apr 2015, 19:04

Re: Der AVR-/ARDUINO-Faden

Beitrag von Bumbum »

Hallo,

kennt sich hier jemand mit Cache-Control Header aus? Ich habe in einem Arduino mit ESP32 einen WebServer:

Code: Alles auswählen

#include <WebServer.h>
WebServer server (HTTP_port);
Bei diesem definiere ich diverse Dateien, unter anderem auch Bilder. z.B.:

Code: Alles auswählen

server.on (FavIcon_ico_path,            [&]() { webserver_handle_binary (FavIcon_ico_name, FavIcon_ico_content_type, FavIcon_ico_size, FavIcon_ico_data); });
Die Binären Dateien, bzw. Bilder liefere ich dann so aus:

Code: Alles auswählen

void webserver_handle_binary (String filename, String content_type, size_t filesize, const char *content)
{
  String header = "";
  header += F ("HTTP/1.1 200 OK\r\n");
  //header += F ("Last-Modified: Mon, 10 April 2023 00:00:00 GMT\r\n");
  header += F ("cache-control: max-age=604800\r\n");
  header += F ("content-Type: ");
  header += content_type;
  header += F ("\r\n");
  header += F ("content-Length: ");
  header += String (filesize);
  header += F ("\r\n");
  header += F ("\r\n");

  server.sendHeader (filename, header, false);
  //server.setContentLength (filesize);
  server.sendContent (content, filesize);
}
Allerdings klappt das nicht. Im Browser werden die Dateien nicht "gecached". Dies habe ich in den Entwickler-Tools des Browsers geprüft und die Dateien werden auch jedes mal tatsächlich neu geladen.
Weiß jemand, was hier schief läuft? Die auskommentierten Zeilen habe ich beide schon einzeln und zusammen versucht. Und ich habe "Cache-Control" auch schon mit dem ersten Buchstaben groß geschrieben.
In einen Meta-Header-Tag kann ich den Cache-Control, nicht packen, da es den bei Bildern ja nicht gibt.

Viele Grüße
Andreas
Benutzeravatar
ferdimh
Beiträge: 9379
Registriert: Fr 16. Aug 2013, 15:19

Re: Der AVR-/ARDUINO-Faden

Beitrag von ferdimh »

Hightech: Zum Zwangsaufwecken ist diese Schaltung ein bisschen problematisch, weil der Eingang dabei, bevor das Ding erwacht, den Linearbereich durchläuft. Dabei wird das Ding mächtig Strom für einige Zeit (5mA oder so) ziehen.

ein 4541 Langzeittimer könnte geeigneter sein, allerdings halten sich die Hersteller hier bedeckt, wie viel Strom das Ding in der Praxis braucht. Auf jeden Fall braucht der Oszillator dann Widerstände im MΩ-Bereich.

Bastelbruder würde ich zutrauen, die Stromaufnahme zu kennen
Jannyboy
Beiträge: 1406
Registriert: So 11. Aug 2013, 14:49
Wohnort: Kreis Augsburg

Re: Der AVR-/ARDUINO-Faden

Beitrag von Jannyboy »

Der Deep-Sleep hat nur eine Macke wenn der timer auf den internen 150kHz RC Oszillator läuft.
Den kann mal auch auf einen 32kHz Uhrenquarz laufen lassen. Dann sollte der ohne Probleme gehen.
Mit dem idf-Framework muss man nur ein Compiler-Switch ändern. Bei der Arduino SDK ist es aufwendiger. Die muss mit den richtigen Switchs neu kompiliert werden und ist dann nur noch mit Uhrenquarz verwendbar.

Grüße Jan
Benutzeravatar
Hightech
Beiträge: 11306
Registriert: So 11. Aug 2013, 18:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Hightech »

Den externen Quarz kann man hier einfach einschalten?
https://docs.espressif.com/projects/esp ... tc-clk-src
Antworten