Sunray CE

WhatATest

Active member
Ive been making changes to make Sunray fit my needs better for a while now, so I thought might aswell post it here in case anyone prefers it over stock.

List of changes that I can remember:
- Virtual gps antenna position.
- Better dead reckoning (no gps/invalid/float).
- Sonar improvements.
- Adaptive mowing speed.
- Configurable speed for perimeter.
- Better odometry and pwm.
- Better motor current monitoring.
- Some bug fixes, and maybe new ones.

Firmware is mostly up to date with master, Ive kept a few things out because I didnt want to bloat Sunray any more that it already is.
No idea if it works with Alfred.

The default config file needs to be properly set up, lots of things are set up for my mower.

 
Interesting, do you mind if I copy some of your improvements? I am curious about the IMU and Odo improvements.

Do you have any idea, how to enable the IMU acceleration readout for x ,y,z ? Once I tried and failed, only getting zeros. Id like to build an obstacle detection because of acceleration
 
Today successfully updated to latest master branch, with my changes… time to look at your improvements 😅
 
Interesting, do you mind if I copy some of your improvements? I am curious about the IMU and Odo improvements.

Do you have any idea, how to enable the IMU acceleration readout for x ,y,z ? Once I tried and failed, only getting zeros. Id like to build an obstacle detection because of acceleration
Sure.
There is a bunch of stuff that mas made a while ago and it wont show on the commits, you might need to dig for that.

Yes, I assume you mean for the MPUs.
You need to set this flag:
Then they should be available here IIRC:
 
1. Basically using the IMUs absolute orientation to offset GPS position. The main advantage is having tilt compensation.
2. Using the IMUs absolute orientation to estimate position, better and configurable heading fusion, allowing the mower to run on invalid for a set amount of seconds. Nothing crazy like a kalman filter but it improves on the original a bit.

Here is an old PR that I made for Sunray with the relevant cahnges:
I have made more changes that are not on that PR, but you can get an idea of how things work from it.
 
Zuletzt bearbeitet:
1. Basically using the IMUs absolute orientation to offset GPS position. The main advantage is having tilt compensation.
2. Using the IMUs absolute orientation to estimate position, better and configurable heading fusion, allowing the mower to run on invalid for a set amount of seconds. Nothing crazy like a kalman filter but it improves on the original a bit.

Here is an old PR that I made for Sunray with the relevant cahnges:
I have made more changes that are not on that PR, but you can get an idea of how things work from it.
OK it's not exactly what i have thought ,but help me to see how i can manage polygon mower geometry.
Actually GPS antenna is locate in the axe of the drive wheel, On big mower like robomow RL 2000 the distance between antenna and front bumper is so big that you can have trouble to mow near wall or other big obstacle.
Certainly the full mower geometry need to be implemented in the firmware.
 
Hi.
@WhatATest Some question about GPS config:

what is the utility of MINCNO:
CPG_CONFIG_FILTER_MINCNO 30 // 30dbHz

and the dynmodel and deactivation of baidou and SBAS
setValueSuccess &= configGPS.addCfgValset8(UBLOX_CFG_NAVSPG_DYNMODEL, 11); // Robotic mower dynmodel

I test this new setting in my mower but not better than the standard value under tree and near wall.

Thanks.
 
UBLOX_CFG_NAVSPG_INFIL_MINCNO rejects gps signals below those dbHZ.
Dynmodels is set to robotic mower now, I think its supposed to adjuct internal variables in its rtk filter to match the kinematics of the set model.
Ardusimple recomends to disable baidou and sbas IIRC.

I was trying to get rid of some weird false fixes, I think it did improve things, not completely sure.
 
Zuletzt bearbeitet:
Few more changes:

- Mow motor rpm control
- Fixed resume operation after watchdog triggers
- Configurable watchdog timer
- Configurable slowdown on heading error (useful for slippery slopes)
- Force fix under 3cm precision in floating mode

Something interesting that I found for those who use their own base station:
Sunray doesnt seem to use the high precision part for RELPOSNED, not sure how much of a difference that would make, but it does get used in HPPOSLLH:
Maybe worth looking into.
 
Zuletzt bearbeitet:
This correction is the reason why NTRIP is less accurate than the own base station. There is an error in the code. The unpack algorithm only produces unsigned values. Exact positions can be obtained with the following change:
case 0x14:
{ // UBX-NAV-HPPOSLLH
iTOW = (unsigned long)this->unpack_int32(4);
int lonHP = this->unpack_int8(24);
if(lonHP > 128) lonHP -= 256;
int latHP = this->unpack_int8(25);
if(latHP > 128) latHP -= 256;
int heightHP = this->unpack_int8(26);
if(heightHP > 128) heightHP -= 256;
lon = (1e-7 * (this->unpack_int32(8) + ((float)lonHP * 1e-2)));
lat = (1e-7 * (this->unpack_int32(12) + ((float)latHP * 1e-2)));
height = (1e-3 * (this->unpack_int32(16) + ((float)heightHP * 1e-2))); // HAE (WGS84 height)
//height = (1e-3 * (this->unpack_int32(20) + (this->unpack_int8(27) * 1e-2))); // MSL height
hAccuracy = ((double)((unsigned long)this->unpack_int32(28))) * 0.1 / 1000.0;
vAccuracy = ((double)((unsigned long)this->unpack_int32(32))) * 0.1 / 1000.0;
accuracy = sqrt(sq(hAccuracy) + sq(vAccuracy));
// long hMSL = this->unpack_int32(16);
//unsigned long hAcc = (unsigned long)this->unpack_int32(20);
//unsigned long vAcc = (unsigned long)this->unpack_int32(24);
if (verbose) {
CONSOLE.print("UBX-NAV-HPPOSLLH ");
CONSOLE.print("lon=");
CONSOLE.print(lon,8);
CONSOLE.print(" lat=");
CONSOLE.println(lat,8);
}
}
break;
and
case 0x3C:
{ // UBX-NAV-RELPOSNED
iTOW = (unsigned long)this->unpack_int32(4);
int relPosHPN = this->unpack_int8(32);
if(relPosHPN > 128) relPosHPN -= 256;
int relPosHPE = this->unpack_int8(33);
if(relPosHPE > 128) relPosHPE -= 256;
int relPosHPD = this->unpack_int8(34);
if(relPosHPD > 128) relPosHPD -= 256;
relPosN = ((float)this->unpack_int32(8) + ((float)relPosHPN / 100.0))/100.0;
relPosE = ((float)this->unpack_int32(12) + ((float)relPosHPE / 100.0))/100.0;
relPosD = ((float)this->unpack_int32(16) + ((float)relPosHPD / 100.0))/100.0;


solution = (SolType)((this->unpack_int32(60) >> 3) & 3);
solutionAvail = true;
solutionTimeout=millis() + 1000;
if (verbose){
CONSOLE.print("UBX-NAV-RELPOSNED ");
CONSOLE.print("n=");
CONSOLE.print(relPosN,2);
CONSOLE.print(" e=");
CONSOLE.print(relPosE,2);
CONSOLE.print(" sol=");
CONSOLE.print(solution);
CONSOLE.print(" ");
switch(solution){
case 0:
CONSOLE.print("invalid");
break;
case 1:
CONSOLE.print("float");
break;
case 2:
CONSOLE.print("fix");
break;
default:
CONSOLE.print("unknown");
break;
}
CONSOLE.println();
}
}
break;
}
break;
 
@Silberstreifen Thanks! I have corrected our UBX-NAV-HPPOSLLH decoder code (not yet tested: https://github.com/Ardumower/Sunray...89c32e0ae27ab/sunray/src/ublox/ublox.cpp#L445) - I think the UBX-NAV-RELPOSNED decoding does not work on 64 bit compilers (e.g. Raspberry OS 64 bit). This seem to be working on 64 bit: https://github.com/Ardumower/Sunray...89c32e0ae27ab/sunray/src/ublox/ublox.cpp#L541 (without the int conversion I get incorrect results with 64 bit compilers for this sample value: https://github.com/Ardumower/Sunray...089c32e0ae27ab/sunray/src/ublox/ublox.cpp#L59 ) BTW: we had a similar issue with 64 bit compilers regarding the MPU/IMU code that we fixed here: https://github.com/Ardumower/Sunray/issues/150
 
Zuletzt bearbeitet:
You are right @Silberstreifen, we dont get signed ints!

I think this is the correct casting, works for me:
Code:
lon = 1e-7 * ((double)(signed long)this->unpack_int32(8) + ((double)(signed char)this->unpack_int8(24) * 1e-2));
lat = 1e-7 * ((double)(signed long)this->unpack_int32(12) + ((double)(signed char)this->unpack_int8(25) * 1e-2));
height = 1e-3 * ((double)(signed long)this->unpack_int32(16) + ((double)(signed char)this->unpack_int8(26) * 0.1)); // HAE (WGS84 height)

The ublox pdf says 1byte signed for HP and 4byte signed for lat/lon.
Same for RELPOSNED.
 
Zuletzt bearbeitet:
I think the UBX-NAV-RELPOSNED decoding does not work on 64 bit compilers (e.g. Raspberry OS 64 bit). This seem to be working on 64 bit: https://github.com/Ardumower/Sunray...89c32e0ae27ab/sunray/src/ublox/ublox.cpp#L541 (without the int conversion I get incorrect results with 64 bit compilers for this sample value: https://github.com/Ardumower/Sunray...089c32e0ae27ab/sunray/src/ublox/ublox.cpp#L59 )
did you solve that problem? I wounder, why you don't use the hp-values for rel. position. On my Adafruit-system these values are fine.
 
Its been a while, here is a list of some of the new changes:
  • Perimiter and exclusion offsets for pathfinder
  • Simplified a lot of the code
  • Reverse OP checks perimeter before backing off
  • Much improved motor control:
    • Dynamic loop time
    • Proper PID
    • Simle FeedFordward model
    • Acceleration limiter
  • Stuck detection
  • Simplified obstacle detection
  • Probably more I dont remember
 
Zuletzt bearbeitet:
For me the battery voltage readings oscillate a lot based on the current being drawn, the voltage readings being used to stop charging or stop mowing are not the actual values the battery is at.
Apparently this can be easily fixed, battery voltage becomes:

batteryVoltage = getBatteryVoltage() + motorCurrent * voltageDropFactor
or
batteryVoltage = getBatteryVoltage() - chargerCurrent * chargeVoltageFactor

This is how the voltage plot looks after the change:
bat.png
 
Zuletzt bearbeitet:
If you add an offset based on measured current you will have always an incorrect voltage. I think it is better to use a current gradient for calculations instead of absolute value
 
Oben