Sunray modding Spielwiese

:ROFLMAO:
If the error happens frequently enough or you know how to trigger it yes, you can walk with a laptop behind the robot.

Other option is SD card loging which can be enabled in the cofig file.
The most comfortable one would be having a raspberry PI connected to the due and your network and monitor the output from there, but that takes a bit of setup.
 
Zuletzt bearbeitet:
Actually yes, could be regen. I think I changed something just to test from whatAtest ce fw, and I get negative current somewhat. I wanted to get rid of it again, but I couldn't find it -_- ... I am to stupid to find why it's giving negatives beside some ifs. But I am not sure if the battery driver is reading that?
 
Hi!,
I am wondering how to activate Mow-Motor once the RC-Mode is on. So - I want to press and hold the button to three-times beep = RC Mode. The Mow-Motor should run as long as the RC-Mode is active. Alternative triggering the Mow-Motor on the third PPM Input - but this is more code I guess.

So, can please someone help me where to change the Code?
I guess in "rcmodel.ccp" somewhere in "if (RC_Mode) { }" somthing for Mow-Motor-start -> true?
(This is where the PPM signal is beeing read in)

Thanks for Help!

David
 
Take a look in the RC.cpp, there pwm is already inside. Just uncomment all mow lines and add a const for enable mowmotor. Or use the tilt pin on the board for rpm/pwm from your rc channel

Code:
// Ardumower Sunray

// this works with a 2,4ghz rc receiver low voltage directly connected from servo/driver pwm receiver output to digital interrupt"capable"
// input pins of ardumower pcb (not too many... rc connector has 4, but only 2 are interrupt capable, that´s why here the tilt Pin is used for mow motor)
// low voltage means that rc receiver is powered directly from the pcb 5volt distributor array without anything else
// -- > calculate and map the pwm modulated channel inputs from the receiver to according values for linear and angular speeds,
// also switch on rc mow flag and set rpm or pwm for mow driver in motor.cpp with .h include vars (could use globals?)

#include "config.h"
#include "rcmodel.h"
#include "robot.h"
#include "motor.h"
#include <RunningMedian.h>

RunningMedian<unsigned int, 5> CHAN_1_med;
RunningMedian<unsigned int, 5> CHAN_2_med;
RunningMedian<unsigned int, 5> CHAN_3_med;

bool bMow = false;

float CHAN_1x;            //Channel 1 RC --- float for SetLinearAngular function (linear)
float CHAN_2x;            //Channel 2 RC --- float for SetLinearAngular function (angular)
int CHAN_3;               //Channel 3 RC --- mapped to +-8Bits: -255 .. 255

volatile unsigned long PPM_start_linear = 0;
volatile unsigned long PPM_end_linear = 0;               
volatile unsigned long PPM_start_angular = 0;
volatile unsigned long PPM_end_angular = 0 ;       
volatile unsigned long PPM_start_mow = 0;
volatile unsigned long PPM_end_mow = 0 ;     


void get_lin_PPM()                                                        // Interrupt Service Routine
{
  if (digitalRead(pinRemoteMow)==HIGH) PPM_start_linear = micros(); 
  else                                   PPM_end_linear = micros();   
}

void get_ang_PPM()                                                        // Interrupt Service Routine
{
  if (digitalRead(pinRemoteSteer)==HIGH) PPM_start_angular = micros(); 
  else                                   PPM_end_angular = micros(); 
}

void get_mow_PPM()                                                        // Interrupt Service Routine
{
  if (digitalRead(pinLift)==HIGH) PPM_start_mow = micros(); 
  else                                   PPM_end_mow = micros(); 
}



void RCModel::begin()
{                                   
  RC_Mode = false;
  nextControlTime = 0;

  pinMode(pinRemoteMow, INPUT);
  pinMode(pinRemoteSteer, INPUT);
  pinMode(pinLift, INPUT); 
  pinMode(pinRemoteSwitch, OUTPUT);     //Relaisboard IN2 for Powerup RC Receiver, K2 switching Receiver Ground On/Off
  digitalWrite(pinRemoteSwitch, HIGH);  //RC Receiver ausschalten und auf RC_Mode warten
 
#ifdef RC_DEBUG
  nextOutputTime = millis() + 1000;
#endif
}

void RCModel::run()
{
  unsigned long t = millis();
  if (!RCMODEL_ENABLE) return;
  if (t < nextControlTime) return;
  nextControlTime = t + 50;                                                           // save CPU resources by running at 20 Hz
 
  if (stateButton == 3){                                                              // 3 button beeps
      stateButton = 0;                                                                // reset button state
      RC_Mode = !RC_Mode;                                                             // R/C-Mode toggle
      if (RC_Mode)  {                                                                 // R/C-Mode ist aktiv
        CONSOLE.println("button mode 3 - RC Mode ON");
        buzzer.sound(SND_ERROR, true);                                                // 3x Piep für R/C aktiv       
        digitalWrite(pinRemoteSwitch, LOW);                                         // RC Receiver Powerup over Relaisboard K2
        attachInterrupt(digitalPinToInterrupt(pinRemoteMow), get_lin_PPM, CHANGE);  // Interrupt aktivieren
        attachInterrupt(digitalPinToInterrupt(pinRemoteSteer), get_ang_PPM, CHANGE);  // Interrupt aktivieren
        attachInterrupt(digitalPinToInterrupt(pinLift), get_mow_PPM, CHANGE);         // Interrupt aktivieren
      }
      if (!RC_Mode) {                 
        CONSOLE.println("button mode 3 - RC Mode OFF");                               // R/C-Mode inaktiv
        buzzer.sound(SND_WARNING, true);                                              // 2x Piiiiiiiep für R/C aus
        motor.setLinearAngularSpeed(0, 0);
        motor.setMowState(false);
        motor.mowRPM_RC = 0;
        motor.mowPWM_RC = 0;
        digitalWrite(pinRemoteSwitch, HIGH);                                        // RC Receiver Powerdown over Relaisboard K2
        detachInterrupt(digitalPinToInterrupt(pinRemoteMow));                       // Interrupt deaktivieren
        detachInterrupt(digitalPinToInterrupt(pinRemoteSteer));                       // Interrupt deaktivieren
        detachInterrupt(digitalPinToInterrupt(pinLift));                              // Interrupt deaktivieren

      }   
  }
 
  if (RC_Mode)   
  {
    battery.resetIdle();                                                        // dont turn mower off in rc mode cause of idletime...
    if (stateButton == 2)                                                       // 2 button beeps
    {                                                                           // Workaround um Mähwerk im RC Modus zu aktivieren
      bMow = !bMow;
      stateButton = 0; 
    }
        
    //lin_PPM = 0;
    if (PPM_start_linear < PPM_end_linear) lin_PWM = PPM_end_linear - PPM_start_linear;
    if (lin_PWM < 2001 && lin_PWM > 999)                                        // Wert innerhalb 1100 bis 1900µsec
    {
      CHAN_1_med.add(lin_PWM);
      CHAN_1_med.getMedian(lin_PWM);
      CHAN_1x = map(lin_PWM, 1000, 2000, -600, 600);
      CHAN_1x /= 1000.0;
      if ((CHAN_1x < 0.02) && (CHAN_1x > -0.02)) CHAN_1x = 0;                   // NullLage vergrössern
      rc_linear = CHAN_1x;                                                    // Weitergabe
    }

    //ang_PPM = 0;
    if (PPM_start_angular < PPM_end_angular) ang_PWM = PPM_end_angular - PPM_start_angular;
    if (ang_PWM < 2001 && ang_PWM > 999)                                        // Wert innerhalb 1100 bis 1900µsec
    {
      CHAN_2_med.add(ang_PWM);
      CHAN_2_med.getMedian(ang_PWM);   
      CHAN_2x = map(ang_PWM, 1000, 2000, -PI*1000, PI*1000);
      CHAN_2x /= 1000.0;
      if ((CHAN_2x < 0.01) && (CHAN_2x > -0.01)) CHAN_2x = 0;                   // NullLage vergrössern         
      rc_angular = CHAN_2x;
    }
    
    //mowmotor
    if (PPM_start_mow < PPM_end_mow) mow_PWM = PPM_end_mow - PPM_start_mow;
    if (mow_PWM < 2101 && mow_PWM > 899)                                      // Wert innerhalb 1100 bis 1900µsec
    {
      CHAN_3_med.add(mow_PWM);
      CHAN_3_med.getMedian(mow_PWM);
      CHAN_3 = (mow_PWM - 1500) / 2;                                          // halbieren... -255 | +255
      if (CHAN_3 > 50 || CHAN_3 < -50) bMow = true;
        else bMow = false;   
      rc_mowPWM = CHAN_3;
      rc_mowRPM= 4000/255 * abs(CHAN_3);

      if (USE_MOW_RPM_SET) motor.mowRPM_RC = rc_mowRPM;
      else motor.mowPWM_RC = rc_mowPWM;
    }
/*#ifdef RC_DEBUG
    if (t >= nextOutputTime)
    {
      nextOutputTime = t + 1000;
      //CONSOLE.println(PWMLeft);
      //CONSOLE.println(PWMRight);
      //CONSOLE.print("RC: linearPPM= ");
      //CONSOLE.print(linearPPM);
      //CONSOLE.print("RC: linear_PPM= ");
      //CONSOLE.print(lin_PPM);   
      //CONSOLE.print("RC: angularPPM= ");
      //CONSOLE.print(angularPPM);
      //CONSOLE.print("RC: angular_PPM= ");
      //CONSOLE.print(ang_PPM);
      //CONSOLE.print("RC: mowPPM= ");
      //CONSOLE.print(mowPPM);
      //CONSOLE.print("RC: mow_PPM= ");
      //CONSOLE.print(mow_PPM);
    }
#endif*/
   motor.setLinearAngularSpeed(rc_linear, rc_angular, false);                     // R/C Signale an Motor leiten
   if (bMow != motor.switchedOn) motor.setMowState(bMow);                         // bMow vom Poti als Schwellwertschalter
  }
}
 
:ROFLMAO:
If the error happens frequently enough or you know how to trigger it yes, you can walk with a laptop behind the robot.

Other option is SD card loging which can be enabled in the cofig file.
The most comfortable one would be having a raspberry PI connected to the due and your network and monitor the output from there, but that takes a bit of setup.
I should probably investigate if I can record serial output with an old smartphone. I can't trigger it reliably enough to walk around with a laptop :).

Actually yes, could be regen. I think I changed something just to test from whatAtest ce fw, and I get negative current somewhat. I wanted to get rid of it again, but I couldn't find it -_- ... I am to stupid to find why it's giving negatives beside some ifs. But I am not sure if the battery driver is reading that?
If you could point me in a direction of the code where the docked state is determined I can also experiment a bit.
  • If docked state would be determined based only on seeing a negative current. I would assume adding an extra condition on charging voltage would prevent a false positive.
  • Potentially even a range check on docking gps point versus actual position (but I assume this will not prevent all cases)
 
I'm quite a poor issue reporter for now since I still didn't progress with a good way to log serial output.

But I do have a few items coming back regularly:
  • The mower drives correctly in his dock, making contact with the charger points. However the charging relay does not turn on.
    When I reboot the robot in such case (without changing its position), the charging relay closes as expected (during IMU calibration).
    I assume the software sometimes gets stuck and doesn't execute completely ?
  • If I (re)boot the mower in its docking station, the mower still tries to rotate in its station when asked to go to mow / undock. Not sure if there is inherently movement needed before it can judge what needs to happen or if I'm missing some parameters? e.g. When I boot it outside and first ask to dock, it typically undocks ok afterwards.
    • I thought I could work around this "turn after reboot in docking station" by just asking a move command backwards (through the cassandra-api). But it seems like move commands are ignored when the mower is charging / docked. I'm not sure if this is intentionally or just a problem of my robot.
Sorry for just describing them without any recorded logs ... .
 
Hi, beide Probleme hängen zusammen. Charge wird nicht sauber erkannt. Wenn er kein Charge in der Dokingstation hat, fährt er nicht rückwärts raus sondern dreht zum nächsten Mähpunkt.
Ich würde folgendes tun.
Relevante Kontakte nachlöten und die Leiterplatte mit Isopropan(Apotheke) von Lötrückstanden befreien.(Krichstrom)
Testen ob das Relays bei Ladestrom sauber anzieht und auch schaltet. Ohne Mainbord und dann mit Mainboard.
Wenn der Fehler immer noch da ist, hat der Mosfet meist Q2 einen Schaden. Neuen einlöten.
Ladekontakte und weg bis zum Mainboard auf Oxidation überprüfen.
Viel Erfolg
 
Hallo könnte mir jemand auf die Sprünge helfen warum das erstellen mit folgendden Fehlern abbricht.

/home/pi/Sunray/sunray/rcmodel.cpp: In function ‘void get_lin_PPM()’:
/home/pi/Sunray/sunray/rcmodel.cpp:41:19: error: ‘pinRemoteMow’ was not declared in this scope
41 | if (digitalRead(pinRemoteMow)==HIGH) PPM_start_linear = micros();
| ^~~~~~~~~~~~
/home/pi/Sunray/sunray/rcmodel.cpp: In function ‘void get_ang_PPM()’:
/home/pi/Sunray/sunray/rcmodel.cpp:47:19: error: ‘pinRemoteSteer’ was not declared in this scope
47 | if (digitalRead(pinRemoteSteer)==HIGH) PPM_start_angular = micros();
| ^~~~~~~~~~~~~~
/home/pi/Sunray/sunray/rcmodel.cpp: In function ‘void get_mow_PPM()’:
/home/pi/Sunray/sunray/rcmodel.cpp:53:19: error: ‘pinLift’ was not declared in this scope; did you mean ‘init’?
53 | if (digitalRead(pinLift)==HIGH) PPM_start_mow = micros();
| ^~~~~~~
| init
/home/pi/Sunray/sunray/rcmodel.cpp: In member function ‘void RCModel::begin()’:
/home/pi/Sunray/sunray/rcmodel.cpp:64:11: error: ‘pinRemoteMow’ was not declared in this scope
64 | pinMode(pinRemoteMow, INPUT);
| ^~~~~~~~~~~~
/home/pi/Sunray/sunray/rcmodel.cpp:65:11: error: ‘pinRemoteSteer’ was not declared in this scope
65 | pinMode(pinRemoteSteer, INPUT);
| ^~~~~~~~~~~~~~
/home/pi/Sunray/sunray/rcmodel.cpp:66:11: error: ‘pinLift’ was not declared in this scope; did you mean ‘init’?
66 | pinMode(pinLift, INPUT);
| ^~~~~~~
| init
/home/pi/Sunray/sunray/rcmodel.cpp:67:11: error: ‘pinRemoteSwitch’ was not declared in this scope
67 | pinMode(pinRemoteSwitch, OUTPUT); //Relaisboard IN2 for Powerup RC Receiver, K2 switching Receiver Ground On/Off
| ^~~~~~~~~~~~~~~
/home/pi/Sunray/sunray/rcmodel.cpp:74:7: error: ‘RCMODEL_ENABLE’ was not declared in this scope
74 | if (RCMODEL_ENABLE)
| ^~~~~~~~~~~~~~
/home/pi/Sunray/sunray/rcmodel.cpp: In member function ‘void RCModel::run()’:
/home/pi/Sunray/sunray/rcmodel.cpp:84:8: error: ‘RCMODEL_ENABLE’ was not declared in this scope
84 | if (!RCMODEL_ENABLE) return;
| ^~~~~~~~~~~~~~
/home/pi/Sunray/sunray/rcmodel.cpp:94:22: error: ‘pinRemoteSwitch’ was not declared in this scope
94 | digitalWrite(pinRemoteSwitch, LOW); // RC Receiver Powerup over Relaisboard K2
| ^~~~~~~~~~~~~~~
/home/pi/Sunray/sunray/rcmodel.cpp:95:47: error: ‘pinRemoteMow’ was not declared in this scope
95 | attachInterrupt(digitalPinToInterrupt(pinRemoteMow), get_lin_PPM, CHANGE); // Interrupt aktivieren
| ^~~~~~~~~~~~
/home/pi/Sunray/sunray/rcmodel.cpp:96:47: error: ‘pinRemoteSteer’ was not declared in this scope
96 | attachInterrupt(digitalPinToInterrupt(pinRemoteSteer), get_ang_PPM, CHANGE); // Interrupt aktivieren
| ^~~~~~~~~~~~~~
/home/pi/Sunray/sunray/rcmodel.cpp:97:47: error: ‘pinLift’ was not declared in this scope; did you mean ‘init’?
97 | attachInterrupt(digitalPinToInterrupt(pinLift), get_mow_PPM, CHANGE); // Interrupt aktivieren
| ^~~~~~~
| init
/home/pi/Sunray/sunray/rcmodel.cpp:105:22: error: ‘pinRemoteSwitch’ was not declared in this scope
105 | digitalWrite(pinRemoteSwitch, HIGH); // RC Receiver Powerdown over Relaisboard K2
| ^~~~~~~~~~~~~~~
/home/pi/Sunray/sunray/rcmodel.cpp:106:47: error: ‘pinRemoteMow’ was not declared in this scope
106 | detachInterrupt(digitalPinToInterrupt(pinRemoteMow)); // Interrupt deaktivieren
| ^~~~~~~~~~~~
/home/pi/Sunray/sunray/rcmodel.cpp:107:47: error: ‘pinRemoteSteer’ was not declared in this scope
107 | detachInterrupt(digitalPinToInterrupt(pinRemoteSteer)); // Interrupt deaktivieren
| ^~~~~~~~~~~~~~
/home/pi/Sunray/sunray/rcmodel.cpp:108:47: error: ‘pinLift’ was not declared in this scope; did you mean ‘init’?
108 | detachInterrupt(digitalPinToInterrupt(pinLift)); // Interrupt deaktivieren
| ^~~~~~~
| init
make[2]: *** [CMakeFiles/sunray.dir/build.make:986: CMakeFiles/sunray.dir/home/pi/Sunray/sunray/rcmodel.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/sunray.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
 
I'm quite a poor issue reporter for now since I still didn't progress with a good way to log serial output.

But I do have a few items coming back regularly:
  • The mower drives correctly in his dock, making contact with the charger points. However the charging relay does not turn on.
    When I reboot the robot in such case (without changing its position), the charging relay closes as expected (during IMU calibration).
    I assume the software sometimes gets stuck and doesn't execute completely ?
  • If I (re)boot the mower in its docking station, the mower still tries to rotate in its station when asked to go to mow / undock. Not sure if there is inherently movement needed before it can judge what needs to happen or if I'm missing some parameters? e.g. When I boot it outside and first ask to dock, it typically undocks ok afterwards.
    • I thought I could work around this "turn after reboot in docking station" by just asking a move command backwards (through the cassandra-api). But it seems like move commands are ignored when the mower is charging / docked. I'm not sure if this is intentionally or just a problem of my robot.
Sorry for just describing them without any recorded logs ... .
It's like @Hartmut mentioned, the mower seems not to be in dock btw. ChargeOp. In the serial dump state, you can check charge voltage and batt voltage . Charge voltage needs to be higher than batt voltage, or mower might not recognize chargerconnected = true
 
Btw. there's an experiment at GitHub master now. Mower will run with 50hz and enhanced obstacle behavior. There's quite some stuff, testing right now. Runs well. Needs mpu IMU hardware.
 
Irgendwie scheinen in der config.h die pins nicht zugewiesen zu sein? Hast du die rc_model.
Aktuell habe ich die rcmodel.h aus deinem release 322-4 auf einen Alfred mit einem RPI 4.


rcmodel.h:
// Ardumower Sunray

// R/C model control

// use PCB pin 'mow' for R/C model control speed and PCB pin 'steering' for R/C model control steering,
// also connect 5v and GND and activate model R/C control via PCB P20 start button for 3 sec.



#ifndef RCMODEL_H
#define RCMODEL_H



class RCModel {
public:
void begin();
void run();
int mowPWM_RC;
//bool RC_Mode;
protected:
float lin_PPM ;
float linearPPM ;
float ang_PPM ;
float angularPPM ;
float mow_PPM ;
float mowPPM ;

unsigned long nextControlTime ;
private:
#ifdef RC_DEBUG
unsigned long nextOutputTime;
#endif
};


#endif

Die entsprechende config.h habe ich auf den Alfred angepasst. Hier zu sehen
 
Wenn du RC nicht brauchst, kommentiere erstmal alles aus in der RC.cpp wo er einen not defined wirft. Du kannst auch probieren die defines in der config.h einfügen. Die sind in der ardumower config.h unten am Ende.
 
Hi, beide Probleme hängen zusammen. Charge wird nicht sauber erkannt. Wenn er kein Charge in der Dokingstation hat, fährt er nicht rückwärts raus sondern dreht zum nächsten Mähpunkt.
Ich würde folgendes tun.
Relevante Kontakte nachlöten und die Leiterplatte mit Isopropan(Apotheke) von Lötrückstanden befreien.(Krichstrom)
Testen ob das Relays bei Ladestrom sauber anzieht und auch schaltet. Ohne Mainbord und dann mit Mainboard.
Wenn der Fehler immer noch da ist, hat der Mosfet meist Q2 einen Schaden. Neuen einlöten.
Ladekontakte und weg bis zum Mainboard auf Oxidation überprüfen.
Viel Erfolg
just to make sure:
" charging issue": The mower does report the docked state (just not charging state) and its charging points are making contact. If I play with the charging points (connecting / disconnecting / pressing) during this event it doesn't go to charge. If I reboot the mower it immediately starts charging without problem. Charging current is 1.5-1.7A typically, so seems ok.

Anyway, I need to spend time getting a decent serial monitoring in place or debugging will not be efficient :).
 
Zuletzt bearbeitet:
nur um sicherzugehen:
„Ladeproblem“: Der Mäher meldet den angedockten Zustand (nur nicht den Ladezustand) und seine Ladepunkte haben Kontakt. Wenn ich während dieses Vorgangs mit den Ladepunkten spiele (anschließen / trennen / drücken), wird er nicht aufgeladen. Wenn ich den Mäher neu starte, beginnt er sofort und ohne Probleme mit dem Laden. Der Ladestrom beträgt normalerweise 1,5–1,7 A, scheint also in Ordnung zu sein.

Wie dem auch sei, ich muss Zeit investieren, um eine vernünftige serielle Überwachung einzurichten, sonst wird das Debuggen nicht effizient sein :).
 
just to make sure:
" charging issue": The mower does report the docked state (just not charging state) and its charging points are making contact. If I play with the charging points (connecting / disconnecting / pressing) during this event it doesn't go to charge. If I reboot the mower it immediately starts charging without problem. Charging current is 1.5-1.7A typically, so seems ok.

Anyway, I need to spend time getting a decent serial monitoring in place or debugging will not be efficient :).
You have a low band filter on voltage reading,so it can cause what you see.
But normally not a problem if battery is very low charging process need to start correctly.

Try to mow up to 23.5 or 24V and send mower to dock to be sure.
 
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/
 
Zuletzt bearbeitet:
Wenn du RC nicht brauchst, kommentiere erstmal alles aus in der RC.cpp wo er einen not defined wirft. Du kannst auch probieren die defines in der config.h einfügen. Die sind in der ardumower config.h unten am Ende.
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.

 
Oben