Fix HGLRC F722 Baro on BF 4.2.11 or 4.3:
set baro_bustype = SPI
set baro_spi_device = 1
set baro_i2c_device = 0
save
Fix HGLRC F722 Baro on BF 4.2.11 or 4.3:
set baro_bustype = SPI
set baro_spi_device = 1
set baro_i2c_device = 0
save
Ich digitalisiere gerade meine Kassettensammlung. Da hilft es, sich das aufwändige Titeleingeben zu automatisieren.
Voila: mein Lieder-Erkenn-Skript (basierend auf songrec)
Setup: Install gem „zaru“ first!
require 'zaru' TIMEOUT = 12 #seconds semaphore = Mutex.new rename_jobs = [] threads = [] # setup parallel threads to recognize songs - only for not renamed files files = Dir["**/*"].select{|e|[".flac",".opus",".wav",".ogg",".mp3",".aac"].include?(File.extname(e).downcase)} # only audio files files.each_with_index do |f, i| rename_jobs << [] threads << Thread.new do new_name = File.dirname(f)+"/" new_name = File.join(File.dirname(f), $1) if f =~ /^([abcd]?\d+)/i new_name = File.join(File.dirname(f), $1) if f =~ /^(track\s*\d+)/i name = `songrec recognize \"#{f}\"`.strip new_name += " - #{Zaru.sanitize!(name)}#{File.extname(f)}" semaphore.synchronize { rename_jobs[i] = [f, new_name] } end end # wait smart and timeout when number of recognized songs doesn't go up old_num = 0 timeout = 0 while(true) do break unless rename_jobs.include?([]) break if timeout > TIMEOUT sleep 1 num_recog = rename_jobs.select{|e|e!=[]}.size if num_recog != old_num timeout = 0 old_num = num_recog else timeout += 1 end puts "#{num_recog} of #{rename_jobs.size} songs recognized yet." end threads.each{|t|t.exit unless t.status} # end remaining searches puts "Preview:" rename_jobs.sort.each {|e| p e} puts "\nEnter y to continue" s = gets.strip if s == 'y' # finally do the renaming c = 0 rename_jobs.each do |r| if r != [] File.rename(r[0], r[1]) c += 1 end end puts "#{c} files renamed." end
Ich hab einen neuen Flieger gebaut.
Mit 80g und 500mm Spannweite ein eher kleines Exemplar. Ein kleiner Reaktionstrainer 🙂
Ausstattung:
2x EMAX ES9051 4,7g Servo (ca. 10€)
FrSky X4R-SB Empfänger
Brotherhobby Returner R3 1106-5100kv (13,16€)
HQProp 3025 Propeller
Sunrise 11A BLHELI_32 mit BEC ESC (ca. 12€)
Robbe Speedy Wing Kit (9,99€)
Trimmung:
Neutralstellung ca. 1-2mm tiefer als die Fläche.
Ausschläge ca. 10mm
Ich hab mir eine helle Taschenlampe eingebildet.
Da kam mir die Astrolux EC06 im Angebot mit Gutschein für ~64 Euro gerade recht.
Die Lampe ist so groß wie ca. eine Getränkedose 0,33l.
Da drin liefern 3x 21700er LiIonen-Zellen (nicht mitgeliefert) den Saft.
6x Cree XHP50.2 machen Licht. Eine solche kann bis zu 2654lm erreichen. Die Lampe wird mit bis zu 16000lm beworben, könnte also stimmen. Der Strahl ist recht breit.
Die Lampe wiegt leer schon fast 500g.
Man kann sie auch mit USB laden.
Die Steuerung ist Open-Source, Anduril 2. Einfach, aber sehr mächtig.
Wenn man sie anschaltet, ist sie ganz zahm. Per Doppelklick entfaltet sie erst die volle Power – da geht dann die Sonne auf. Es ist blendend hell!
Arduino on Lilygo OLED Lora ESP32 (board TTGO-Lora32-OLED V1″)
#define USE_OLED
#ifdef USE_OLED
//Libraries for OLED Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#endif
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
const char *ssid = "GPSWIFI";
const char *password = "12345678";
WiFiServer server(80);
const unsigned char ubxRate1Hz[] =
{ 0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00 };
const unsigned char ubxRate5Hz[] =
{ 0x06,0x08,0x06,0x00,200,0x00,0x01,0x00,0x01,0x00 };
const unsigned char ubxRate10Hz[] =
{ 0x06,0x08,0x06,0x00,100,0x00,0x01,0x00,0x01,0x00 };
const unsigned char ubxRate16Hz[] =
{ 0x06,0x08,0x06,0x00,50,0x00,0x01,0x00,0x01,0x00 };
// Disable specific NMEA sentences
const unsigned char ubxDisableGGA[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01 };
const unsigned char ubxDisableGLL[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01 };
const unsigned char ubxDisableGSA[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01 };
const unsigned char ubxDisableGSV[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01 };
const unsigned char ubxDisableRMC[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01 };
const unsigned char ubxDisableVTG[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01 };
const unsigned char ubxDisableZDA[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x08,0x00,0x00,0x00,0x00,0x00,0x01 };
#define Battadc 36
#define ADC_FACTOR (0.000635*2.0*1.362)
#define BATT_LOW 3.5
#define SDA 21
#define SCL 22
#ifdef USE_OLED
//OLED pins
#define OLED_SDA 4
#define OLED_SCL 15
#define OLED_RST 16
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);
#endif
bool enable_dbg;
bool sig_valid, sig_rxok;
float sig_speed, saved_spd;
int sig_sats;
#define NUM_V_ENTRIES 5
float maxspeed[NUM_V_ENTRIES];
int vbatt;
// Cut out the wanted substring from a comma-separated string
static String extract_val(char *buf, int len, int cpos)
{
String str="";
int i,cc=0,cs=0,ce=255;
for (i=0;i<len;i++) {
if (buf[i]==',') {
cc++; // count commas
if(cc==cpos) cs=i+1;
if(cc==cpos+1) {ce=i; break;}
}
else if (buf[i]=='*' || buf[i]=='\r')
ce=i;
}
if (cs == 0) // no comma seen - no result
return str;
int s = min(ce-cs, 255);
for (i=0; i<s; i++) // build string, could be nicer...
str+=(char)buf[cs+i];
// memcpy(tgt, &buf[cs], s);
return str;
}
void parse_gps(char c) {
static char buf[127];
static int pos=0;
if (c=='\n') {
buf[pos]=0;
if (buf[2]=='V' && buf[3]=='T' && buf[4]=='G') {
sig_rxok = true;
String s = extract_val(buf, pos, 7);
if (s.length() > 0)
sig_valid = true;
Serial.println(s);
sig_speed = s.toFloat();
saved_spd = sig_speed;
}
else if (buf[2]=='G' && buf[3]=='G' && buf[4]=='A') {
#ifdef USE_OLED
display.print(buf);
#endif
String s = extract_val(buf
, pos, 7);
Serial.println(s);
sig_sats = s.toInt();
}
}
else if (c=='$') pos=0;
else if (pos < sizeof(buf))
buf[pos++] = c;
}
//Warteschleife, die ankommende Daten vom GPS Modul verarbeitet und den Status des Tasters prüft
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (Serial2.available()) {
char c=Serial2.read();
parse_gps(c);
if (enable_dbg) Serial.print(c);
//display.print(c);
}
//display.display();
} while (millis() - start < ms);
}
static void sendUBX( const unsigned char *progmemBytes, size_t len )
{
Serial2.write( 0xB5 ); // SYNC1
Serial2.write( 0x62 ); // SYNC2
uint8_t a = 0, b = 0;
while (len-- > 0) {
uint8_t c = ( *progmemBytes++ );
a += c;
b += a;
Serial2.write( c );
}
Serial2.write( a ); // CHECKSUM A
Serial2.write( b ); // CHECKSUM B
delay(100);
}
static void updateRate()
{
sendUBX(ubxRate5Hz, 10);
}
void setup() {
pinMode(0, INPUT_PULLUP); // button
pinMode(SCL, INPUT_PULLUP); // I2C of GPS compass
pinMode(SDA, INPUT_PULLUP);
// analogSetAttenuation(ADC_0db); // control sensitivity; ADC_11db, ADC_6db, ADC_2_5db, ADC_0db
// pinMode(Battadc, INPUT);
// adcAttachPin(Battadc);
Serial.begin(115200); // debug
Serial2.begin(9600,SERIAL_8N1,12,13); // GPS
#ifdef USE_OLED
//reset OLED display via software
pinMode(OLED_RST, OUTPUT);
digitalWrite(OLED_RST, LOW);
delay(20);
digitalWrite(OLED_RST, HIGH);
//initialize OLED
Wire.begin(OLED_SDA, OLED_SCL);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) { // Address 0x3C for 128x32
//Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
#endif
// setup WIFI server
WiFi.softAP(ssid, password);
IPAddress myIP = WiFi.softAPIP(); // usually 192.168.4.1
server.begin();
#ifdef USE_OLED
display.setTextColor(WHITE);
display.setTextSize(1);
display.clearDisplay();
display.setCursor(0, 0);
display.println("Simon's WIFI GPS");
display.println("IP address:");
display.println(myIP);
display.display();
#endif
delay(2000);
sendUBX(ubxDisableGLL, 12);
sendUBX(ubxDisableGSA, 12);
sendUBX(ubxDisableGSV, 12);
sendUBX(ubxDisableRMC, 12);
sendUBX(ubxDisableZDA, 12);
Serial2.print("$PUBX,41,1,0007,0003,19200,0*25\r\n");
Serial2.flush();
delay(100);
Serial2.end();
Serial2.begin(19200,SERIAL_8N1,12,13);
delay(1000);
updateRate();
}
void wifi() {
WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
char i;
Serial.println("New Client."); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
// Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// the content of the HTTP response follows the header:
char tmp[32];
client.print("<html><head><meta http-equiv=\"refresh\" content=\"10; URL=/\" /></head>");
client.print("<body style=\"background-color:black;\"><h1 style=\"color:white;font-size:80px\">Simon's WIFI GPS</h1>");
client.println("<p style=\"color:white;font-size:60px\"><b>");
sprintf(tmp, "Max = %4.1f km/h", maxspeed[0]);
client.print(tmp);
client.println("</p><p style=\"color:white;font-size:30px\">");
for (i=1;i<NUM_V_ENTRIES;i++) {
sprintf(tmp, "%4.1f km/h", maxspeed[i]);
client.print(tmp);
client.println("<br>");
}
sprintf(tmp, "<br>Batt = %2.3f V", (float)vbatt*ADC_FACTOR);
client.print(tmp);
client.println("<br>");
sprintf(tmp, "<br>Signal rx ok = %d", sig_rxok);
client.print(tmp);
client.println("<br>");
sprintf(tmp, "<br># of satellites = %d", sig_sats);
client.print(tmp);
client.println("<br>");
client.print("<br><br><a href=\"/R\">RESET</a> Vmax.<br></p></body></html>");
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
} else { // if you got a newline, then clear currentLine:
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
// Check to see if the client request was "GET /H" or "GET /L":
if (currentLine.endsWith("GET /R")) {
for (i=0; i<NUM_V_ENTRIES; i++)
maxspeed[i] = 0.0;
}
}
}
// close the connection:
client.stop();
// Serial.println("Client Disconnected.");
}
}
void loop() {
int i;
bool spdwritten = false;
char tmp[32];
float spd;
smartdelay(0);
#ifdef USE_OLED
display.clearDisplay(); // drawString(x,y,text);? or ACROBOTIC_SSD1306 with setTextXY/putString
display.setCursor(0, 0);
#endif
if (sig_valid) {
spd = sig_speed;
sig_speed = 0.0;
// show maximum speed, with 5 places to see glitches
#ifdef USE_OLED
display.println("Geschwindigkeit (max)");
#endif
for (i=0; i<NUM_V_ENTRIES; i++) {
if (spd > maxspeed[i] && !spdwritten) {
maxspeed[i] = spd;
spdwritten = true;
break;
}
}
#ifdef USE_OLED
for (i=0; i<NUM_V_ENTRIES; i++) {
if (i==0)
display.setTextSize(2);
sprintf(tmp, "%4.1f km/h", maxspeed[i]);
display.println(tmp);
if (i==0)
display.setTextSize(1);
}
// show current speed
sprintf(tmp,"S%4.1f Sats %3d", saved_spd, sig_sats);
display.print(tmp);
} else {
display.println("No GPS fix.");
if (sig_rxok)
display.println("GPS RX ok");
sprintf(tmp," Sats %3d", sig_sats);
display.print(tmp);
#endif
}
vbatt = analogRead(Battadc);
#ifdef USE_OLED
if ((float)vbatt*ADC_FACTOR < BATT_LOW) {
display.setCursor(108, 32);
display.print("LOW");
}
display.display();
#endif
if (digitalRead(0)==0) { // clear
for (i=0;i<NUM_V_ENTRIES; i++)
maxspeed[i] = 0.0;
#ifdef USE_OLED
display.clearDisplay();
#endif
}
wifi();
}
installiere minidlna (nach https://wiki.ubuntuusers.de/ReadyMedia/)
sudo apt-get install minidlna
setze interface z.B. wlo1
network_interface=wlo1 friendly_name=Laptop inotify=yes media_dir=V,/var/lib/minidlna/videos media_dir=A,/var/lib/minidlna/music
kopiere Zeug in /var/lib/minidlna
gib Rechte 644 auf die Dateien
find /var/lib/minidlna/videos -type f -exec chmod 0644 {} \;
restart server
Edit /etc/default/minidlna
to contain (and also /lib/systemd/system/minidlna.service)
USER=simon
GROUP=simon
Then /etc/minidlna.conf
to contain
user=simon
I also had to change permissions to allow my user
sudo chown simon:simon /var/cache/minidlna
sudo chown simon:simon /run/minidlna
Then restart the service
sudo service minidlna restart
sudo service minidlna force-reload
Mit meinem neuen, viel besseren 3D-Drucker Artillery Genius Pro macht es natürlich mehr Freude, was zu drucken. So freuen sich auch Freunde, Verwandte und Bekannte über Gadgets und Figürchen…
Damit das auch weiterhin so klappt, decke ich mich natürlich mit Druckmaterial ein. Schließlich will man ja auch etwas Auswahl haben…
Mein altes PLA-Filament von „HERZ“ (ebay; weiß und signalrot) druckt trotz vernachlässigter Lagerung tadellos – es hat hier 50% Luftfeuchte, scheint aber nicht zu schaden. Das rote druckt absolut präzise, gleichförmige Layer. Das weiße ist etwas unruhig und „batzig“ – das war im Anet A8 schlimm. Es verstopft manchmal. Der Artillery hat da fast keine Probleme. Kein Stringing, in weitem Temperaturbereich. Die Haftung auf der Genius-Glasplatte ist extrem, teilweise habe ich Angst um die Druckplatte. Da hilft nur Abkühlen und das dauert recht lange. Ich drucke mit 205°C/60°C und 60mm/s. Die Layerhaftung ist sehr gut. Das PLA wird recht spröde. Belastete Teile halten nicht lang.
Das PETG grau von Amazon Basics (im Angebot für knapp 17€/kg) dagegen gefällt mir nicht so gut. Es ist nicht stabiler. Es haftet fast gar nicht. Die Farbe ist recht hell.
Neulich habe ich mit ein paar Farben (weiß
, gelb, grün, blau, pink) PLA von Material4Print eingedeckt. Der Preis ist fair, so ca. 16 Euro. Es sind aber 750g-Spulen. Das PLA stringt deutlich und hat eine schlechtere Layerhaftung. Da bin ich wohl von meinem „Edelfilament“ verwöhnt. Die Farben sind dafür schön. Da werde ich mal einen Temptower drucken müssen. Stellt sich grade raus, das M4P PLA will mit 215° oder gar 220° gedruckt werden, dann passt auch die Festigkeit und das Stringing!Dafür habe ich noch frisch „Performance PLA“ und „Performance ABS“, sowie Flex in weiß und schwarz von INKRAYON im Angebot geordert. Da bin ich mal gespannt.
Der VNA ist ja schön und gut, was die Abstimmung der Antennen betrifft.
Aber er sagt nur wenig über die Reichweite aus.
Daher kommt hier Test #2.
Aufbau: VNA auf 5800MHz mit der ImmersionRC CL als Testsender.
Daneben dann das ImmersionRC-Powermeter mit dem DUT.
Der Abstand wird in der stärksten „Keule“ so lange vergrößert
, bis das Messlimit von -40dBm erreicht ist. Dieser Abstand wird mit einem Lineal von Gehäuse zu Gehäuse gemessen und notiert.Klar, das hat sicher auch seine Fehler. Antennen werden immer von Antennengehäuse zu Gehäuse gemessen. Da sind lange Helix evtl im Nachteil.
Die Frequenz ist fix auf 5800 – das ist sicher nicht für alle Antennen das Optimum.
Die Reproduzierbarkeit ist gut. Wiederholtes Anschließen von Aomway CL und TrueRC X-Air zwischen den Tests zeigen immer die gleiche Entfernung.
Sender: ImmersionRC Spironet CL | Mehr = besser [cm] | Anmerkung |
AXII 2 CL lang | 9 | hat einen 90° SMA |
Aomway CL | 11 | |
Aomway CL | 7 | mit U.FL-Adapter |
Aomway CL #2 | 7 | |
CnG CL | 12 | |
Lum. Pagoda | 7 | |
Lum. Pagoda #2 | 9 | |
TBS Triumph Stubby | 9 | |
TBS Triumph | 7 | |
Hawkeye CL | 9 | |
rote Pagoda | 5 | |
UXII Stubby | 6 | |
TrueRC Singularity lang | 8 | |
Foxeer CL | 9 | |
CnG Helix 6 Windungen | 25 | |
AXII mini Patch 8.4dBi | 27 | mit Winkel |
TrueRC X-Air 10dBi | 26 | |
TrueRC X-Air 10dBi | 28 | mit Winkel |
Ethix Crosshair 10.25dBi | 23 | mit Winkel |
AXII Duo Patch 12.2dBi | 34 | mit Winkel |
Aomway Helix 8 Windungen | 22 | |
Aomway Triple 8dBi | 31 | |
Aomway Triple 8dBi | 19 | verlängert |
Realacc Triple 8dBi | 28 | |
Fatshark Big Patch 13dBi | 39 | Krass |
Furious Pokerchip 10dBi | 27 | |
Menace Invader 6.5dBi | 18 | |
Prodrone 3,5 Helix v2 8.8dBi | 34 | recht eng |
Prodrone Mi-Cross V2 9dBi | 24 | |
Prodrone v3 Extreem Cross-Air 10dBi | 27 | |
Furious Nano CL | 10 | U.FL |
Rush Cherry | 10 | U.FL |
TBS Triumph nano | 9 | U.FL |
Realacc Trident nano | 5 | U.FL |
TBS Dipol | 8 | U.FL |
noname Dipol dünn | 8 | U.FL |
noname Dipol dünn #2 | 8 | U.FL |
Eachine Dipol lang | 8 | U.FL |
Eachine Dipol kurz | 6 | U.FL |
Fazit:
Von den Omnis/CL beeindrucken die eine Aomway und die CnG (Chips&Grips-Selbstbau). Die meisten anderen schlagen sich aber auch ok. Wie stark die Abstrahlung ungleich verteilt ist, habe ich nicht getestet.
Die UXII-Stubby und rote China-Pagoda fallen durch. Auch die Realacc Trident ist Mist.
Mit dem U.FL-Adapter schlagen sich die Furious CL und die Rush Cherry sehr gut. Die Rush ähnelt optisch sehr der Caddx-Vista-Antenne (nur ist die LHCP).
Bei den Richtantennen bleibt die große Fatshark Patch der King. Aber diese Antenne ist groß, unpraktisch, muss verlängert werden (was den Gewinn wieder schmälert) und hat einen extrem kleinen Öffnungswinkel.
Der eigentliche Sieger ist daher die Lumenier AXII Duo Patch – mit kaum geringerer Reichweite, aber inklusive SMA-Winkel und großem horizontalen Öffnungswinkel. Sie ist auch eine der teuersten Antennen hier. Am VNA fällt auf, dass sie etwas niederohmig daherkommt, was vom Winkeladapter fast komplett kompensiert wird. Das fällt auch bei der anderen modernen Lumenier-Patch aus dem Long-Range-Kit auf. Da hat der Hersteller sich wohl Gedanken über die Benutzung in der Praxis gemacht. Die Zahlen geben ihm jedenfalls Recht!
Preis-Leistungs-Tipp bei den Patch-Antennen ist die Poker Chip von FuriousFPV. Die kostet knapp 10 Euro, klein ist sie auch. Das Design ist auch cool.
Enttäuscht bin ich von der Menace Invader, aber die gibt auch nur 6,5dBi Gewinn an. Die Ethix gewinnt auch keinen Blumentopf hier, in der 10dBi-Klasse spielt die nicht mit.
Die Triplefeeds sind ok, aber sperrig und mit Verlängerung leidet die Performance. Ich habe beide mit 50 Ohm am zweiten Anschluss terminiert.
Das mit dem fehlenden OSD bei DJI-Goggles-Recording ist schon schade.
Aber es gibt einen Workaround. Wenn man denn die Telemetrie in der Funke per SD-Log wegspeichert. Leider klappt das nur unter Windows…
Man nehme
Video und Telemetrie-Log auf PC kopieren.
Ablauf: