Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 18:54 25 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Micromite vs a ESP32 for a project.

Author Message
Gizmo

Admin Group

Joined: 05/06/2004
Location: Australia
Posts: 5078
Posted: 04:22am 28 Apr 2024
Copy link to clipboard 
Print this post

Hi guys.

Long post sorry.

Been working on a rover project for a while, the long term goal is a lawn mower. The rolling chassis is built, its about the size of a small ride on lawn mower. Apart from the brains, its using a compass module using a I2C interface for direction finding, a home brew motor controller that can be programmed to take whatever format of data I want to use, a RTK GPS module paired with a base station, a RC receiver, and a telemetry link back to a PC.

My earlier "brains" was a ESP32 with some software I had written. It worked, but had issues keeping a straight line, more of a banana shaped curve, though always ended up at each waypoint within a few cm. Next step was to write a PC interface so I could monitor the rover, send it new waypoints, etc.

Then I took a different path, fell for the spin, bought a flight computer and installed Ardurover, which is coupled with Mission Planner software on the PC. This took about 3 months to get working properly, but still has issues like overshooting the waypoint, is overly complicated, poorly documented and has one hell of a learning curve.

I realised this was probably the wrong way to go, I should have stuck with the ESP32 and improved my code. I did think of a solution for the banana lines. I still need to write the PC interface.

So back to plan A.

For the PC software I fired up JUSTBasic, its got some good graphics functions which I need ( Aerial photo, rover positioned on the map, waypoints displayed and moved with the mouse, etc ). I've got the software to a point where it receives serial telemetry data from a ESP01 ( test chip ), and displays things like the GPS position, direction, battery voltage, etc, etc. I can also send commands back to the chip to do things like stop, go home, new waypoint file, etc.

I'm still using the ESP32 as the brains of the rover. Maybe it shouldn't be.

I hate the arduino code and IDE. Its fickle. Yesterday I suddenly found it wouldn't compile my code anymore, even old previously working code. Seams all of a sudden I need to put all the functions at the top of the program instead of the bottom or it complains about undeclared variable. I declare all my variables at the top, function at the bottom. For some reason it now compiles bottom to top, and raises a error. "You compiled this just fine a few months ago!"

So, what I'm asking is, should I be using a Micromite?

The code isnt that busy. Read GPS data every second, parse the data and get the Lat,Long. Read the compas. Do some maths, adjust the motor speeds. Send the telemetry. Any requests coming back? The existing ESP32 code is below.

The only real issue is can I interface with the HMC5883 compass module. Probably.

What are peoples thoughts on this.

Notes on code. I removed the sample GSP data as it points to my house.
This code works, it had 4 waypoints and would just drive around a big square in my yard.


#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>

float DeclinationAngle=0.17; // Radians.  http://www.magnetic-declination.com/

Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);

int DriveMode=0;
 // 0=Stationary
 // 1=Turn to face waypoint
 // 2=Travel to waypoint
int StartPos=0;
int EndPos=0;  

int Steer=0; // -10 to 10, left to right
float GotFix=0;
int BiasLeft=0;
int BiasRight=0;
double OriginLat=0;
double OriginLng=0;
double DestLat=0;
double DestLng=0;
double DestinationAngle=0;
String GPSString="";
String GPSSentence="";
String GPSTime="";
double GPSLat=0;
double GPSLng=0;
float Distance=0; // Distance to next waypoint
int WayPoint=0;
int WayPointTotal=4;
double WayPointLat[100];
double WayPointLng[100];
String NS="";
String EW="";
int GPSFix=0;
float TargetBearing=0; // Direction from old to new waypoint
int WheelLVal=0;
int WheelRVal=0;
int WheelRTarget=0;
int WheelLTarget=0;
int SpeedFactor=0;
int Craw=2;
int Walk=4;
int Run=6;
int D=0;
int Button1Pin=A6; // Switch
int Button2Pin=A0; // Left up down
int Button3Pin=A3; // Right up down
int ButtonMode=0; // 0=off. 1=Auto. 2=Manual
int Button1=0; // Switch
int Button2=0; // Left up down
int Button3=0; // Right up down

#define RX1     26  // GPS Data in from GPS module SimpleRTK2B.
#define TX1     25  // Free, Motor controller?

#define RX2     32  // Telemetry In
#define TX2     33  // Telemetry Out

int Drive(int WheelLeft, int WheelRight){
 // Right wheel is 64
 // Left wheel is 192
 // increased number is forward
 // This was for the original Sabretooth controler, which blew up.
 int Motor=0;
 if(WheelLeft>10){WheelLeft=10;}
 if(WheelRight>10){WheelRight=10;}
 if(WheelLeft<-10){WheelLeft=-10;}
 if(WheelRight<-10){WheelRight=-10;}
 
 while(WheelLVal!=WheelLeft || WheelRVal!=WheelRight){
   if(WheelLVal<WheelLeft){WheelLVal=WheelLVal+1;}
   if(WheelLVal>WheelLeft){WheelLVal=WheelLVal-1;}
   if(WheelRVal<WheelRight){WheelRVal=WheelRVal+1;}
   if(WheelRVal>WheelRight){WheelRVal=WheelRVal-1;}
   Motor=(WheelRVal*SpeedFactor)+64;
   Serial1.write(Motor);
   Motor=(WheelLVal*SpeedFactor)+192;
   Serial1.write(Motor);
   delay(50); // Ramping
 }
 
 if(WheelLeft==0 && WheelRight==0){
   // All stop
   Serial1.write(0);
 }
 WheelLVal=WheelLeft;
 WheelRVal=WheelRight;
 //delay(100);
 return 0;
}

int Rotate(int NewBearing){
 Drive(0,0);
 int Bearing=ReadCompas();
 Serial2.println("[<TXT>Turning from " + String(Bearing) + " to " + String(NewBearing) + "</TXT>]");
 if((Bearing+360)>(NewBearing+360)){
    Drive(-10,10);
    while((Bearing+360)>(NewBearing+360)){
     Bearing=ReadCompas();
     delay(20);
    }
 }else{
    Drive(10,-10);
    while((Bearing+360)<(NewBearing+360)){
      Bearing=ReadCompas();
      delay(20);
    }
 }
 Drive(0,0);
 Serial2.println("[<TXT>Turning completed</TXT>]");
 
 return 0;
}
 
int ReadCompas(){
 sensors_event_t event;
 mag.getEvent(&event);
 // Added the +13 and +18 to calibrate the sensor
 double newheading = atan2(event.magnetic.y+13, event.magnetic.x+18);
 newheading+=DeclinationAngle;
 if(newheading < 0){ newheading += 2*PI; }
 if(newheading > 2*PI){ newheading -= 2*PI; }
 int B=int(newheading * 180/M_PI);
 Serial2.println("[<COM>" + String(B) + "</COM>]");
 return B;
}

int GetNewHeading(double La1, double Lo1, double La2,  double Lo2){
 int X= 360 - ( atan2((La2-La1), (Lo2-Lo1)) * 180 / 3.14159265 ) + 90;
 if(X>=360){X=X-360;}
 return X;
}

float GetDistance(double La1, double Lo1, double La2,  double Lo2){
 double R = 6378.137; // Radius of earth in KM
 double dLat = La2 * 3.14159265 / 180 - La1 * 3.14159265 / 180;
 double dLon = Lo2 * 3.14159265 / 180 - Lo1 * 3.14159265 / 180;
 double a = sin(dLat/2) * sin(dLat/2) + cos(La1 * 3.14159265 / 180) * cos(La2 * 3.14159265 / 180) * sin(dLon/2) * sin(dLon/2);
 double c = 2 * atan2(sqrt(a), sqrt(1-a));
 double d = R * c * 1000;
 return d; // meters
}

void GetLocation(){
 while (Serial1.available() > 0){
   GPSString+=char(Serial1.read());
 }
 if(GPSString.indexOf("GNGSA")>0){
   StartPos=GPSString.indexOf("GGA")+4;
   EndPos=GPSString.indexOf("GSA")-4;
   if(EndPos>StartPos){
     GPSSentence=GPSString.substring(StartPos,EndPos);
     GPSTime=GPSSentence.substring(0,GPSSentence.indexOf(","));
     GPSSentence=GPSSentence.substring(GPSSentence.indexOf(",")+1,GPSSentence.length());
     GPSLat=GPSSentence.substring(0,GPSSentence.indexOf(",")).toDouble();
     GPSSentence=GPSSentence.substring(GPSSentence.indexOf(",")+1,GPSSentence.length());
     NS=GPSSentence.substring(0,GPSSentence.indexOf(","));
     GPSSentence=GPSSentence.substring(GPSSentence.indexOf(",")+1,GPSSentence.length());
     GPSLng=GPSSentence.substring(0,GPSSentence.indexOf(",")).toDouble();
     GPSSentence=GPSSentence.substring(GPSSentence.indexOf(",")+1,GPSSentence.length());
     EW=GPSSentence.substring(0,GPSSentence.indexOf(","));
     GPSSentence=GPSSentence.substring(GPSSentence.indexOf(",")+1,GPSSentence.length());
     GPSFix=GPSSentence.substring(0,GPSSentence.indexOf(",")).toInt();
     double Temp1=floor(GPSLat/100); //Degrees
     double Temp2=GPSLat-(Temp1*100); //Minutes
     GPSLat=Temp1 + (Temp2/60);
     Temp1=floor(GPSLng/100); //Degrees
     Temp2=GPSLng-(Temp1*100); //Minutes
     GPSLng=Temp1 + (Temp2/60);
   }
   GPSString="";
   
   if(NS=="S"){GPSLat=0-GPSLat;}
   if(EW=="W"){GPSLng=0-GPSLng;}
 }
 return;
}

void setup() {
 
 WayPoint=1;
 WayPointLat[0]=0;
 WayPointLng[0]=0;

 WayPointLat[1]=;
 WayPointLng[1]=;
 WayPointLat[2]=;
 WayPointLng[2]=;
 WayPointLat[3]=;
 WayPointLng[3]=;
 WayPointLat[4]=;
 WayPointLng[4]=;
 
 DestLat=WayPointLat[1];
 DestLng=WayPointLng[1];


 Serial1.begin(115200, SERIAL_8N1, RX1, TX1);

 // Setup serial for telemetry
 Serial2.begin(56700, SERIAL_8N1, RX2, TX2);
 

 // Get the starting position.
 // Make sure we are in the right country at least while the GSP settles down
 while(GPSLat>-20 && GPSLat<-30 && GPSLng<100 && GPSLng>200 ){
   GetLocation();
 }
 WayPointLat[0]=GPSLat;
 WayPointLng[0]=GPSLng;
 OriginLat=GPSLat;
 OriginLng=GPSLng;
 
}

void loop() {
 


 ButtonMode=1;

 if(ButtonMode==1){

   GetLocation();
   int Bearing=ReadCompas();
   
   delay(100);
   // Hack for testing
   if(GPSFix==4 && GPSLat<-20 && GPSLat>-30 && GPSLng>100 && GPSLng<200 ){GPSFix=5;}
   

   if(GPSFix!=5){ DriveMode=0; }
   
   if(GPSFix==5 && DriveMode==0 ){ DriveMode=1;}
   if(DriveMode==0){
     Serial2.print("[<DM>" + String(DriveMode) + "</DM>]"); //Drive mode
     Drive(0,0);
   }
   
   if(DriveMode==1){ // Turn to face next waypoint
     Serial2.print("[<DM>" + String(DriveMode) + "</DM>]"); //Drive mode
     SpeedFactor=Craw;  // Slow for turning
     TargetBearing=GetNewHeading(GPSLat, GPSLng, DestLat,  DestLng);
     if((Bearing+360-5)>(TargetBearing+360) || (Bearing+360+5)<(TargetBearing+360)){
       Rotate(TargetBearing);
     }
     WheelLVal=0;
     WheelRVal=0;
     DriveMode=2;
   }
   
   if(DriveMode==2){
     Serial2.print("[<DM>" + String(DriveMode) + "</DM>]"); //Drive mode
     Distance=GetDistance(GPSLat,GPSLng,DestLat,DestLng);
     
     if(Distance>0.5){
       
       if(Distance<3){
         // We are getting close. Use a compass to closer
         Bearing=ReadCompas();
         TargetBearing=GetNewHeading(GPSLat, GPSLng, DestLat,  DestLng);
         WheelLTarget=WheelLVal;
         WheelRTarget=WheelRVal;
         if(Distance<=1){ SpeedFactor=Craw;}
         if(Distance>1){SpeedFactor=Walk;}
         if(Distance>2){SpeedFactor=Run;}
         
         if(Bearing+360>TargetBearing+360+10 || Bearing+360<TargetBearing+360-10){
           // More that 10 degrees off, stop and rotate.
           Drive(0,0);
           SpeedFactor=Craw;
           Rotate(TargetBearing);
           Drive(10,10);
         }
         if(Bearing+360>TargetBearing+360+5){
             // Turn left a bit
           if(WheelLVal<8 && WheelRVal<15){WheelRTarget=WheelRVal+1;}
           if(WheelLVal>=8){WheelLTarget=WheelLVal-1;}
           Drive(WheelLTarget,WheelRTarget);
         }
         if(Bearing+360<TargetBearing+360-5){
             // Turn right a bit
           if(WheelRVal<8 && WheelLVal<15){WheelLTarget=WheelLVal+1;}
           if(WheelRVal>=8){WheelRTarget=WheelRVal-1;}
           Drive(WheelLTarget,WheelRTarget);
         }
         if(Bearing+360>TargetBearing+360-5 && Bearing+360<TargetBearing+360+5){
             // Going straight
             Drive(10,10);
         }
       }else{
         
       // Add code to see how far we are off the line

       }  



     }else{

       OriginLat=WayPointLat[WayPoint];
       OriginLng=WayPointLng[WayPoint];
       WayPoint++; // Increment Waypoint Counter
       Serial2.print("[<WP>" + String(WayPoint) + "</WP>]"); // Waypoint number
       if(WayPoint>WayPointTotal){WayPoint=1;}
       DestLat=WayPointLat[WayPoint];
       DestLng=WayPointLng[WayPoint];
       
       DriveMode=1; //Aim to new waypoint
       if(DestLng==OriginLng){
         // Avod a divide by zero error OriginLng=OriginLng+0.0000001}


       }else{
         DestinationAngle=(DestLat-OriginLat)/(DestLng-OriginLng);
         DestinationAngle=atan(1/DestinationAngle)*(180/3.1426);
     }
       
       DestLat=WayPointLat[WayPoint];
       DestLng=WayPointLng[WayPoint];
     }
     

   }


 } // End ButtonMode 1


}




Glenn
Edited 2024-04-28 14:53 by Gizmo
The best time to plant a tree was twenty years ago, the second best time is right now.
JAQ
 
Gizmo

Admin Group

Joined: 05/06/2004
Location: Australia
Posts: 5078
Posted: 05:51am 28 Apr 2024
Copy link to clipboard 
Print this post

Adding, I have a spare Pi Pico doing nothing. Loaded up the PicoMite software, dead easy.

Unless someone suggests otherwise, I'll give it a go and see if I can use it on the rover.

Glenn
The best time to plant a tree was twenty years ago, the second best time is right now.
JAQ
 
morgs67
Regular Member

Joined: 10/07/2019
Location: Australia
Posts: 75
Posted: 07:35am 28 Apr 2024
Copy link to clipboard 
Print this post

the picomite is the current flavour of the month. It is currently very well supported and has many more tricks up its' sleeve.

Tony
 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 2135
Posted: 08:07am 28 Apr 2024
Copy link to clipboard 
Print this post

Agree. GPS parsing is all done for you.
  Quote  GPS() The GPS functions are used to return data from a serial communications
channel opened as GPS.
The function GPS(VALID) should be checked before any of these functions are
used to ensure that the returned value is valid.
GPS(ALTITUDE) Returns current altitude (if sentence GGA is enabled).
GPS(DATE) Returns the normal date string corrected for local time e.g. “12-01-2020”.
GPS(DOP) Returns DOP (dilution of precision) value (if sentence GGA is enabled).
GPS(FIX) Returns non zero (true) if the GPS has a fix on sufficient satellites and is
producing valid data.
GPS(GEOID) Returns the geoid-ellipsoid separation (if sentence GGA is enabled).
GPS(LATITUDE) Returns the latitude in degrees as a floating point number, values are negative
for South of equator
GPS(LONGITUDE) Returns the longitude in degrees as a floating point number, values are
negative for West of the meridian.
GPS(SATELLITES) Returns number of satellites in view (if sentence GGA is enabled).
GPS(SPEED) Returns the ground speed in knots as a floating point number.
GPS(TIME) Returns the normal time string corrected for local time e.g. “12:09:33”.
GPS(TRACK) Returns the track over the ground (degrees true) as a floating point number.
GPS(VALID) Returns: 0=invalid data, 1=valid data

Edited 2024-04-28 18:08 by phil99

Footnote added 2024-04-28 21:48 by phil99
Perhaps interpolating intermediate waypoints may help keep it on the straight and narrow.

The Pico uses decimal degrees rather than minutes and seconds making calculation easier. There are a variety of MATH commands / functions that may help too.

The original definition of the metre was 1/10,000,000 of the distance from the pole to the equator. That is also 90 deg. so 1 deg. = 111,111,111 m
If the latitudes of the points are 11.1 m apart they are 0.0001 deg. apart.
For longitude it is the same at the equator but gets less as you move north or south so a bit of trig. will give the value where you are.
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4226
Posted: 10:03am 28 Apr 2024
Copy link to clipboard 
Print this post

Hi Gizmo,

I have been using GPS in geocaching (and in car navigation), but notice that GPS pure from satellites is 1 meter accurate at best. If you have additional information (like a ground station), only then you become more accurate.

I assume you are working with a ground station ? I personally have no idea how the math works when using a ground station, but you must definitely communicate between the 2. Is that why you use a ESP32 (both on the ground station and the rover?
Without ground station the position tolerances will be large.
Even farmers, with large machines, use a ground station. And they have 10meter wide mowers.

I think that is why most automic lawn mowers do not use GPS. Depending the cost price they run a more or less intelligent random algorithm inside a fenced system (ground wire).

For fast rover alignment you will need accelerometers, and maybe even a compass.

Regards,

Volhout
Edited 2024-04-28 20:06 by Volhout
PicomiteVGA PETSCII ROBOTS
 
Gizmo

Admin Group

Joined: 05/06/2004
Location: Australia
Posts: 5078
Posted: 12:23pm 28 Apr 2024
Copy link to clipboard 
Print this post

I'm using a pair of ZED-F9P modules ( about $400 each! ), one as the fixed base station, the other on the rover. The base station sends corrections via a pair of HC-12 modules. The rovers ZED-F9P module does all the maths, and sends the GPS data out another serial port.

I see the GPS commands in the PicoMite manual, but the Fix option may not work for me, as the GPS module has several Fix values with different meaning, eg GPS Float, RTK float, RTK Fix. I wait for the Fix to equal 5 before I let the rover move. Thats sub 5cm accuracy. On a clear day the modules can achieve that accuracy fairly easily.

The code I have to parse the GPS data into Lat, Long and Fix works fine

I use a compass module, it uses I2C, and I'll need to do some research into decoding the data. I found the compass to be fairy accurate, within a few degrees. Its mounted on a PVC mast well away from the motors. If I wanted even better compas readings I can add a third ZED-F9P module to the rover about 1 meter apart from the other one, but they are expensive so I think the compass module will do.

Yeah seen the dumb mowers that need a fence wire. No challenge in building one of those   . I have a few acres I want this thing to mow and want nice straight lines.

Glenn
The best time to plant a tree was twenty years ago, the second best time is right now.
JAQ
 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 2135
Posted: 06:17am 29 Apr 2024
Copy link to clipboard 
Print this post

  Quote  My earlier "brains" was a ESP32 with some software I had written. It worked, but had issues keeping a straight line, more of a banana shaped curve, though always ended up at each waypoint within a few cm.

Some thoughts on this.

The magnetic deviation in much of SE Aus. is 10° to 12° so perhaps the compas starts it out in the wrong direction and the GPS progressively corrects it.
It may be worth returning to the ESP32 and experimenting with adding or subtracting 10° to see if that "de-Queensland's" the banana. If it changes the curve at all experiment with different values.

Another possibility, if that doesn't get it straight enough is to make use of the high precision of your GPS. Subdivide each run into many waypoints a metre or two apart. Then the bananas will be too small to notice.
The intermediate points can be had by interpolating between the start and finish Lat. and Long. points.
 
Gizmo

Admin Group

Joined: 05/06/2004
Location: Australia
Posts: 5078
Posted: 07:15am 29 Apr 2024
Copy link to clipboard 
Print this post

In my code I had the line...

float DeclinationAngle=0.17; // Radians.  http://www.magnetic-declination.com/

This was set for my location and used in the code.

As mentioned I have a fix for the banana shaped lines. Either see how far I was to the side of the line, or a better option, divide a long waypoint to waypoint section into lots of little sub waypoints. If its just aiming for the next sub way point, it wont drift far off the ideal line.

But the code isnt the problem for me, it was just about choice of ESP32 or a Micromite/Picomite option. I really am tired of the Arduino IDE and all its pedantic tantrums. Started translating the C++ code to basic on the picomite last night, have to say its a pleasure to use compared to the arduino IDE process.

Tonight I'll plug in the compass I2C module and see if I can get it working on the picomite.

Glenn
The best time to plant a tree was twenty years ago, the second best time is right now.
JAQ
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4226
Posted: 07:27am 29 Apr 2024
Copy link to clipboard 
Print this post

Glenn,

This is really nice stuff. The F9 modules, and the technology behind it. Expensive, however, the F9 module itself is only 100 dollar, so a JLC PCB would bering the cost down. I hope to learn a lot from this thread. Keep us up to date.

Ublox also have some nice explanations fo the basics behind it on their website. But you are the real pioneer !!!

Volhout
PicomiteVGA PETSCII ROBOTS
 
zeitfest
Guru

Joined: 31/07/2019
Location: Australia
Posts: 482
Posted: 01:35pm 29 Apr 2024
Copy link to clipboard 
Print this post

The ESP32 is from Expressif I think, I guess they supply the foundation compiler and so on used under the IDE. It would be interesting to try compiling the .ino (slightly altered of course) for a pi pico (eg earlphilhower) and see what happens.

The ESP32 and Pico have a lot more resources than a micromite. Most small systems in development seem to have the same problems of bugs, hype and utter BS, you take your pick.
 
stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 2127
Posted: 07:23pm 29 Apr 2024
Copy link to clipboard 
Print this post

I bought an ESP32  https://www.aliexpress.com/item/1005005761340152.html
but don't do arduino c. if only there was basic
 
zeitfest
Guru

Joined: 31/07/2019
Location: Australia
Posts: 482
Posted: 12:05am 30 Apr 2024
Copy link to clipboard 
Print this post

Google gives quite a few ESP32 Basic interpreters - there is even one in ROM (!)
eg (just for interest    )

builtin
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3150
Posted: 01:51am 30 Apr 2024
Copy link to clipboard 
Print this post

  stanleyella said  if only there was basic


Annex Basic is terrific.
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
Gizmo

Admin Group

Joined: 05/06/2004
Location: Australia
Posts: 5078
Posted: 01:55am 30 Apr 2024
Copy link to clipboard 
Print this post

Thats interesting about the basic interpreter built into the ESP's.

OK, got the PicoMite talking to the compass module. That was the only possible hurdle I could see, so its all go ahead for the PicoMite.

I'll post my compass test code in a new thread later.

Glenn
The best time to plant a tree was twenty years ago, the second best time is right now.
JAQ
 
stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 2127
Posted: 04:22pm 30 Apr 2024
Copy link to clipboard 
Print this post

this looks interesting if my board is v2.05 but arduino ide needed it seems.
https://www.hackster.io/sl001/a-vga-computer-based-on-esp32-and-fabgl-with-sound-graphics-976894
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024