Sunray modding Spielwiese

Suche mal nach Battery, da hat Einfach das Problem und eine Lösung für die Battery.cpp beschrieben. In der Version 298 gab es das Problem noch nicht. In der letzten Version besteht aber ein Ladeproblem. Kommt aufs Mainboard 1.4 oder 1.3 und ob gebrückt oder nicht drauf an.
Hatte gestern ein Update auf neuste Version gemacht und heute nur 24 Volt obwohl meine optischsche Ladekontrolle zeigte das er Charge enable hat.
Zurück auf die 298 und er lädt wieder voll.
https://forum.ardumower.de/threads/akku-wird-nicht-voll-geladen.25362/
thank you for the hint. I went through the battery.cpp to realize this batteryvoltageslope (problem in that topic) is not used anymore in this branch/fork :).
 
Hat leider nicht funktioniert danach hat er an der RunningMedian.h abgebroche.

In der Zwischenzeit habe ich mich nochmal mit der config.h vertraut gemacht und einige Formatierungen angepasst und überschüssige Zeichen entfernt.

Du kannst auch die aktuelle master nehmen, da ist die RC cpp aufgeräumt und ein Standard runningmedian wird verwendet, ohne das du eine Bibliothek brauchst. Allerdings brauchst du auch nicht so Vorsichtig sein, du kannst diesen include auch einfach auskommentieren.
 
thank you for the hint. I went through the battery.cpp to realize this batteryvoltageslope (problem in that topic) is not used anymore in this branch/fork :).
How so?

Look at battery.run(), just in the middle there is the slope.. :
Code:
void Battery::run(){
  if (startupPhase == 0) {
    // give some time to establish communication to external hardware etc.
    nextBatteryTime = millis() + 2000;
    startupPhase++;
    return;
  }
  if (millis() < nextBatteryTime) return; 
  nextBatteryTime = millis() + 50;
  if (startupPhase == 1) startupPhase = 2;

  // voltage
  float voltage = batteryDriver.getChargeVoltage();
  if (abs(chargingVoltage-voltage) > 10) {
    chargingVoltage = voltage;
    chargingVoltBatteryVoltDiff = 0;
  }
  chargingVoltage = 0.9 * chargingVoltage + 0.1* voltage;

  //actual_voltage = batteryDriver.getBatteryVoltage();
  //voltage = 0.1 * voltage + (1.0-0.1) * actual_voltage;
  voltage = batteryDriver.getBatteryVoltage();
  if (abs(batteryVoltage-voltage) > 10) {
    batteryVoltage = voltage;
    batteryVoltageLast = voltage;
    chargingVoltBatteryVoltDiff = 0;
  }
  float w = 0.995;
  if (chargerConnectedState) w = 0.9;
  batteryVoltage = w * batteryVoltage + (1-w) * voltage;

  // difference charging voltage and battery voltage
  chargingVoltBatteryVoltDiff = 0.99 * chargingVoltBatteryVoltDiff + 0.01 * (chargingVoltage - batteryVoltage);

  // current
  chargingCurrent = 0.9 * chargingCurrent + 0.1 * batteryDriver.getChargeCurrent(); 
  
  if (!chargerConnectedState){
      if (chargingVoltage > 7){
      chargerConnectedState = true;         
          DEBUG(F("CHARGER CONNECTED chgV="));                           
      DEBUG(chargingVoltage);   
      DEBUG(F(" batV="));
      DEBUGLN(batteryVoltage);
      buzzer.sound(SND_OVERCURRENT, true);     
    }
  }
  
  if (millis() >= nextCheckTime){ 
    nextCheckTime = millis() + 5000;                 
    if (chargerConnectedState){     
      if (chargingVoltage <= 5){
        chargerConnectedState = false;
        nextEnableTime = millis() + 5000;       // reset charging enable time           
        DEBUG(F("CHARGER DISCONNECTED chgV="));
        DEBUG(chargingVoltage);     
        DEBUG(F(" batV="));
        DEBUGLN(batteryVoltage);             
      }
    }           
    timeMinutes = (millis()-chargingStartTime) / 1000 /60;
    if (underVoltage()) {
      DEBUG(F("SWITCHING OFF (undervoltage) batV="));
      DEBUG(batteryVoltage);
      DEBUG("<");
      DEBUGLN(batSwitchOffIfBelow);
      buzzer.sound(SND_OVERCURRENT, true);
      if (switchOffAllowedUndervoltage)  batteryDriver.keepPowerOn(false);   
    } else if ((millis() >= switchOffTime) || (switchOffByOperator)) {
      DEBUGLN(F("SWITCHING OFF (idle timeout)"));           
      buzzer.sound(SND_OVERCURRENT, true);
      if ((switchOffAllowedIdle) || (switchOffByOperator)) batteryDriver.keepPowerOn(false);
    } else batteryDriver.keepPowerOn(true);           

    // battery voltage slope
    float w = 0.999;
    batteryVoltageSlope = w * batteryVoltageSlope + (1-w) * (batteryVoltage - batteryVoltageLast) * 60.0/5.0;   // 5s => 1min
    batteryVoltageLast = batteryVoltage;
  
    if (millis() >= nextSlopeTime){
      nextSlopeTime = millis() + 60000; // 1 minute
      badChargerContactState = false;
      if (chargerConnectedState){
        if (!chargingCompleted){
          if (chargingVoltBatteryVoltDiff < -3.0){
          //if (batteryVoltageSlope < 0){
            badChargerContactState = true;
            DEBUG(F("CHARGER BAD CONTACT chgV="));
            DEBUG(chargingVoltage);
            DEBUG(" batV=");
            DEBUG(batteryVoltage);
            DEBUG(" diffV=");
            DEBUG(chargingVoltBatteryVoltDiff);
            DEBUG(" slope(v/min)=");
            DEBUGLN(batteryVoltageSlope);
          }   
        }
      }
      if (abs(batteryVoltageSlope) < BAT_FULL_SLOPE){
        batteryVoltageSlopeLowCounter = min(10, batteryVoltageSlopeLowCounter + 1);
      } else {
        batteryVoltageSlopeLowCounter = 0; //max(0, batteryVoltageSlopeLowCounter - 1);
      }
    }

        if (millis() >= nextPrintTime){
            nextPrintTime = millis() + 60000;  // 1 minute                 
          
      //print();         
            /*DEBUG(F("charger conn="));
            DEBUG(chargerConnected());
            DEBUG(F(" chgEnabled="));
            DEBUG(chargingEnabled);
            DEBUG(F(" chgTime="));   
            DEBUG(timeMinutes);
            DEBUG(F(" charger: "));   
            DEBUG(chargingVoltage);
            DEBUG(F(" V  ")); 
            DEBUG(chargingCurrent); 
            DEBUG(F(" A "));       
            DEBUG(F(" bat: "));
            DEBUG(batteryVoltage);
            DEBUG(F(" V  ")); 
            DEBUG(F("switchOffAllowed=")); 
            DEBUG(switchOffAllowed);   
            DEBUGLN();      */                 
    } 
  }
 
  if (millis() > nextEnableTime){
    nextEnableTime = millis() + 5000;                 
  
    if (chargerConnectedState){       
        // charger in connected state
        if (chargingEnabled){
          //if ((timeMinutes > 180) || (chargingCurrent < batFullCurrent)) { 
          // https://github.com/Ardumower/Sunray/issues/32             
          if (chargingCompletedDelay > 5) {  // chargingCompleted check first after 6 * 5000ms = 30sec.
            chargingCompleted = ((chargingCurrent <= batFullCurrent) || (batteryVoltage >= batFullVoltage));
          }
          else {         
            chargingCompletedDelay++;
          }       
          if (chargingCompleted) {
            // stop charging
            nextEnableTime = millis() + 1000 * enableChargingTimeout;   // check charging current again in 30 minutes
            chargingCompleted = true;         
            enableCharging(false);
          }
        } else {
           //if (batteryVoltage < startChargingIfBelow) {
              // start charging
              enableCharging(true);
              chargingStartTime = millis();
          //}     
        } 
    }
    else {
      // reset to avoid direct undocking after docking 
      chargingCompleted       = false;
      chargingCompletedDelay  = 0;  // reset chargingCompleteted delay counter
    }

  }


}


First of all, you could enable the sd debug log vor the chargerconnected state. Then you can analyze what is happening.

@goosst I changed the config.h in master, at end of modsection you find DEBUG_BATTERY, set this true. Set SD_LOG also true, then you should have a 10 sec output with some bat data.
 
Zuletzt bearbeitet:
I haven't checked the master on github yet but, in the version I forked:
batteryVoltageSlope itself is nowhere used after the calculation. It just calculates batteryVoltageSlopeLowCounter which is nowhere used in the code (If I commented it out yesterday nothing complained in the code :)).

ok, I should have some time in the weekend to experiment (and try to upgrade to the master branch again).
(I've had not installed the sd-card ... ).

Is it not more efficient actually to work with issues on github?
 
yeah, it has nothing to do specific with suddenly be in docked state... but it´s used to calc the batt full state and cycle the charging if batt is considered full.

i just checked, actually you are totally right. it´s not used afterwards, looks like i missed some code during update XD

But still, this section should deliver some insight to the problem.
 
Zuletzt bearbeitet:
Hallo zusammen,
ich habe mal wieder ein Problem für welchen ich einen Tipp bräuchte woran es liegt. Über einen Hinweis würde ich mich sehr freuen.

Code:
In file included from /home/pi/Sunray/sunray/src/ublox/sfe_bus.cpp:54:
/home/pi/Sunray/sunray/src/ublox/sfe_bus.h:211:10: error: ‘void SparkFun_UBLOX_GNSS::SfePrint::print(const __FlashStringHelper*)’ cannot be overloaded with ‘void SparkFun_UBLOX_GNSS::SfePrint::print(const char*)’
  211 |     void print(const __FlashStringHelper *c)
      |          ^~~~~
/home/pi/Sunray/sunray/src/ublox/sfe_bus.h:206:10: note: previous declaration ‘void SparkFun_UBLOX_GNSS::SfePrint::print(const char*)’
  206 |     void print(const char *c)
      |          ^~~~~
/home/pi/Sunray/sunray/src/ublox/sfe_bus.h:236:10: error: ‘void SparkFun_UBLOX_GNSS::SfePrint::println(const __FlashStringHelper*)’ cannot be overloaded with ‘void SparkFun_UBLOX_GNSS::SfePrint::println(const char*)’
  236 |     void println(const __FlashStringHelper *c)
      |          ^~~~~~~
/home/pi/Sunray/sunray/src/ublox/sfe_bus.h:231:10: note: previous declaration ‘void SparkFun_UBLOX_GNSS::SfePrint::println(const char*)’
  231 |     void println(const char *c)
      |          ^~~~~~~
 
So I hooked up a raspberry pi with a powerbank to monitor the serial output of the arduino due. Very nice looking setup 🙃.
(Should probably just upgrade to a raspberry pi this winter without the esp32 etc. )

The event where the robot just reports "docked" out of the blue, I have not reproduced yet while recording data.
But I might have triggered something in the same line of issues:
  1. Ardumower was charging
  2. gave it a mow command, it slowly moved out of his house (i.e. charger is disconnected now).
  3. Mower seemed confused when getting out of his house (moving a few cm, stopping again, etc.). I've moved it by hand several meters further.
  4. Now mower reported a "docked" status.
  5. After rebooting the mower - through cassandra, not through the emergency button - it is working fine again.

Relevant recorded data:

the charging voltage just remains high / very slowly decades even when not connected to its charger. As a consequence, ardumower just reports docked.
(Disconnecting from charger must have happened where you see the small jump downwards in charging voltage.)
1726420790191.png


2024-09-15 18:08:15,726 root DEBUG charger conn=1 chgEnabled=1 chgTime=42 charger: 25.81 V 0.04 A bat: 26.43 V batslope: 0.01 V
2024-09-15 18:08:15,730 root DEBUG Op::eek:nChargerConnected
2024-09-15 18:08:15,732 root DEBUG setting to docking position


Since after rebooting, voltage looks fine again. I still seem to suspect a software rather than an electrical issue (or I have some sticky relais which gets opened after reboot ...).
 
Zuletzt bearbeitet:
Seems like the charger voltage reading gets stuck.
There is a low pass filter for that voltage but it should be fine.

You can print and log the output of this function: batteryDriver.getChargeVoltage();
Thats just reading directly from the pcb, if it gives you weird values I would suspect hardware.
 
Zuletzt bearbeitet:
Seems like the charger voltage reading gets stuck.
There is a low pass filter for that voltage but it should be fine.

You can print and log the output of this function: batteryDriver.getChargeVoltage();
Thats just reading directly from the pcb, if it gives you weird values I would suspect hardware.
indeed, I seemed to have put serial output of the unfiltered voltage on a poor location in the code ... , will be for next debugging session.

In case of interest, I had triggered something similar when it reported "docked" state during mowing / undocking.
1) mowing: filtered charger voltage = zero
2) docked / charging
3) starting to mow / undocking --> chargervoltage remained high entire time (despite not being in the station).
4) after a few minutes reports to be in docked state (and position jumps back). If there is still charging voltage being measured, I was surprised it still took several minutes to report again the docked state. (it did report charger conn=1 chgEnabled=1 all the time during the driving around.)
1726595679107.png

I suppose I'll need to inspect the Q4 mosfet / relay / Q1 on this bloody pcb. Seems dangerous if a full battery is connected to two naked pins ... .
Sorry for spamming on this software topic, most likely indeed just hardware.
For safety reasons, I could probably also come up with some forced opening of the relay when in a mowing state.
 
Zuletzt bearbeitet:
Hi, i made a quick sumup about most changes:

Code Iteration
- IDLE and DOCK Iteration time is 10 Hz
- Mow Iteration is 50 Hz
- Imu readout > 30 Hz
Mowmotor
- PID controller for RPM of mowmotor (USE_MOW_RPM_SET)
- Different RPM sets for different conditions eg. retry(escapeLawn), mowrpm stalls under xy% of setpoint --> RETRYSLOWSPEED
- Different RPM sets for different conditions eg. slow(escapeLawn), mowrpm stalls under xy% of setpoint --> KEEPSLOWSPEED
Mower states (used for obstacles)
- shouldMoveBackwards?
- shouldMoveForward?
- shouldRotateLeft?
- shouldRotateRight?
- on possible WatchdogReset´s: continue mowing option
Obstacle
- Bumper left and right seperatated
- Obstacles are set based on mower states
- Added IMU obstacles, rotation direction dependent (eg. sudden deflection while shouldMoveForward)
- Faster and improved GPS Obstacles (grab mower during linetracking --> reacts in 1.5 sec)
- Overload Obstacles
- Dockretry Obstacles
- better rotationObstacles (PoPo situation)
- obstacle Chaining during escape ops
noDockRotation
- improved and easier approach and config
- akustik feedback, dock/ undock
Speeds
- alot of custom speeds for all situations
GPS
- Reboot GPS Dock/unDock
- react on GPS Jump activated
- configurable GPS Reset if mower is in float and waits for fix
- before, GPS jump would trigger because of Pathfinder taking too long after escapeOp and not updating position
- now with waitTime
Mower allowed to move with GPS invalid
- configurable Time
Adaptive Speed (Mowpower needs to be validated)
- 2 Options: Mowpower/MowRpm
EscapeLawn (Mowpower needs to be validated)
- 2 Options: Mowpower/MowRpm
- GPS obstacle prohibited in configurable time if escapeLawn triggered
Improvement of mowmotor not starting/ mower moving with not turned on mowmotor
- waitOp when switch off mowmotor
- waitOp when switch on mowmotor
Movement
- refined linetracker
- reworked motor.cpp bugs
- Rotation Ramp, flexible, fast but smooth rotations
- Distance Ramp, improved linear ramp based on target distance
- higher precision in targeting and point reaching (normal terrain)
- transition speed: mower will not stop if next target angle is under x degrees (configurable)
Timing and Calculation
- dismissed alot LP filters, used unfiltered or only slightly smoothed vals
- LP filters now use actual code iteration time and dont freak out on short or very long ite times (pathfinder)
 
Erstmal Danke für Deine Arbeit hier mit Deiner Moddingversion.
Bisher setzte ich die letzten Wochen erfolgreich die Version mit dem letzten Commit aus dem August ein.

Habe nun gestern die aktuelle Version verwendet...kannst Du vielleicht bei ein paar Sachen Licht ins dunkle bringen.
Mir ist nicht ganz klar warum wenn ich bei MOW_RPM_NORMAL z.B. 3000 die Drehzahl nicht erreicht wird, bei mir so um 2500 laut Console auch der PWM Wert ist etwa bei 104. (Verwende den normalen 57BL02 und 4Zahnmesser mit JYQD Treiber) daher fährt er dann immer im langsamen Tempo. Stelle ich auf USE_MOW_RPM_SET false und ADAPTIVE_SPEED_MODE auf 1 für Mowmotorpower, dann geht die Drehzahl des Mähmotors auf über 3400 und er fährt seine eingestellten Geschwindigkeiten.
Mir ist nicht ganz klar warum das mit dem RPM nicht funktioniert, die Drehzahl wird ja angezeigt also auch ermittelt?!
Wie erfolgt die Drehzahlansteuerung per RPM, die Stellgröße bleibt ja PWM?

Dazu hat er gestern 3x den Perimeter verlassen und ist liegen geblieben. Einstellungen sind "eigentlich" die gleichen wie im August, waren auch stellen an den guter Empfang ist (Hecken sind alle gestutzt und kein Haus in der Nähe) mit der Version im August gabs das nie.

Vielleicht könnte man für die
#define DEBUG_STATE_ESTIMATOR false
#define DEBUG_LINETRACKER false
#define DEBUG_MOTORCONTROL false
#define DEBUG_BATTERY false

hier auch noch ein Möglichkeit einbauen, dass vielleicht nur alle Sekunde eine Ausgabe erfolgt, ist sonst echt schwer zu lesen ;-)

Sehe ich das richtig, dass auch eine Geschwindkeitsänderung über Cassandra oder SunrayApp nicht mehr möglich ist weil ja jetzt fest im Code die Geschwindigkeiten bei unterschiedlichen Zuständen vorgegeben ist?

Und ganz vergessen, da wie ich finde auch eine tolle Erweiterung von @WhatATest einen Offset für den Abstand zu den Perimetern hinzuzufügen bei Bedarf.
gab dann noch ein paar Änderungen mit Hinzugefügter Verifikation, vielleicht passt das ja auch noch gut in Deinen Mod.


Danke Dir
 
Zuletzt bearbeitet:
Ok, da Kai im Prinzip auch so etwas mit Perimeter verlassen bzw. watchdog rest --> idle beschreibt, muss davon aussgegangen werden das der .25 Merge kaputt ist.
Das muss ich wohl nochmal machen, bzw. mal testen wann es dazu kommt. Ich werde die .22 als ein neues release Hochladen, da sind alle Änderungen bzw. Neurungen schon drin, aber die aktuellen Sunray Änderungen fehlen dann. Danke für die Beschreibung.

Zu deinen Fragen:

USE_RPM_SET:
Wenn dein Motor die Drehzahl nicht erreicht, musst du den P Anteil des PID Reglers hochziehen. Vorher setzt du RPM_OFFSET noch auf Null. Dann erhöhst dz den P Anteil des Reglers, bis er gerade so nicht um seine Drehzahl schwingt. Dann sollte auch schon mehr RPM da sein. Zu guter letzt trägst du den Offset vom sollwert zum istwert in RPM_OFFSET ein. Die idle Drehzahl sollte zum Sollwert +-150 RPM nicht überschreiten, wenn doch passe den OFFSET an. Ist der OFFSET zu hoch, wie bei dir der Fall, passt der PID Regler wie gesagt nicht. Info: 3600 RPM sind ungefähr das limit, da ist dann 255 pwm erreicht.

SUNRAY Speed:
Die sunray vorgabe sollte weiterhin funktionieren, alle anderen Speeds in der config sind Status speeds.

Ich schaue mal was noch nice to have ist, mir fällt auch vieles ein. Erstmal muss die .25 stabil laufen.

Grüße
 
danke für den Hinweis, dann probier ich das mit dem P-Anteil mal aus.
Aber nochmal echt tolle Arbeit, unglaublich wie flott der Ardumower durch den Garten huschen kann :cool:
und es auch so "Kleinigkeiten" wie Bumper links rechts es endlich mal in den Code geschafft haben.
 
Falls da jemand demnächst zufällig einen log hat, immer her damit. Die ganzen debug Sachen immer auslassen, dann melden sich nur funktionsaufrufe und operations. Das hilft um zu sehen was er gerade vorhatte...
 
Ich nutze seit Juni 24 erfolgreich deine 319-Version, es war wohl, glaube ich , die letzte, bevor du damit auf Github gegangen bist. Seither habe ich die Sache nicht mehr weiter verfolgt, da ich damit voll zufrieden war. Nun habe ich mir das mal wieder angeschaut und festgestellt, dass du eine Menge daran getan hast. Also dachte ich mir, probier ich doch wieder einmal etwas neues.
Nun habe ich aber ein paar Probleme. Die config.h ist ja so umfangreich geworden, dass mir etwas der Überblick fehlt. Ich habe in meinem Ardumower Bürstenmotoren und tue mich etwas schwer, was da für mich alles unzupassen ist, mein Englisch ist auch nicht sehr weitreichend. Ich habe die Änderungen weitgehend aus der vorherigen config übernommen, es ließ sich kompilieren und hochladen, aber ich bekomme keinen GPS-Fix mit der neuen Version, mit der 319 gibt es kein Problem.
Ich kann nichts finden, woran es liegen könnte. Ich hänge mal die config mit an, vielleicht kannst du mal drüber schauen, wo es klemmen könnte, ich wäre dir sehr dankbar!
 
So, ich habe den master reverted, das ist jetzt wieder die 322, aber mit allen Neuerungen. Ich beobachte jetzt noch bevor ich einen aktuellen Release mache.

@jottka : wenn du einen bürsten mähmotor ohne Odo hast, muss alles RPM mäßige abgestellt werden. Wenn du trotzdem adaptive Speed und escape lawn haben willst bzw. probieren willst (ich habe es nicht umfangreich getestet) dann musst du escape lawn und adaptive Speed im Modus 1 laufen lassen, alles über Leistungsberechnung. Die Einstellung musst du leider selbst machen, ich denke aber das die Ausgangswerte in der config schon sinnvoll sind. Ich schaue mal über deine config wenn du magst.

Hast du irgendwann deine ublox mal geupdatet? Wenn nicht solltest du das tun. Der aktuelle masterzweig war leider kaputt, du könntest es nochmal probieren (hat nichts mit watchdog zu tun) aber dort gab es auch GPS ublox config änderungen. Wenn du mit dem jetzigen master keinen fix bekommst, dann kann ich mir vorstellen das deine ublox Firmware alt ist, in der 322 ist nämlich eine andere Bibliothek Verwender (v3)

Wenn du Probleme hast dann schreib sie hier, vllt bekommen wir das ja hin.

Grüße
 
Hi, i made a quick sumup about most changes:
Waw, impressive! Thanks for the overview.
I don't quite understand why all your improvements don't make it into the main sunray project. The robot is barely usable without them ...

- IDLE and DOCK Iteration time is 10 Hz
- Mow Iteration is 50 Hz
- Imu readout > 30 Hz
Just for understanding, which hardware are you using?
Thinking these higher sample rates could start to become a problem on the arduino due.
 
Yes possible. But you could lower it in config, i didnt try IT If everything behaves accordingly. You need an MPU 60 or 90 something... The config Options (when configured properly) should Work with all drivers except CAN right now.

I am using the PCB 1.4 with April BL Drives and an jyqd mowdriver. MPU 60something. Mowmotor is the largest act with the Diameter of original .. so its longer.. and a 29 cm ambrogio angled Blade
 
Oben