Zugegeben, das fand ich selbst etwas übertrieben. Vergleichbar sind die beiden Systeme nur bedingt, was aber der Kreativität keinen Abbruch tut :-)Zitat:
Ich mache zumindest keine Fotos von eintreffenden Paketen usw.
Druckbare Version
Zugegeben, das fand ich selbst etwas übertrieben. Vergleichbar sind die beiden Systeme nur bedingt, was aber der Kreativität keinen Abbruch tut :-)Zitat:
Ich mache zumindest keine Fotos von eintreffenden Paketen usw.
Hi Leute!
Also der Thread ist wirklich "interessant", es zeugt wieder einmal wo unser Roboternetz hingelangt ist und wo es irgendwann mal enden wird. Bitte Leute, hört auf zu "lästern" das ist nicht Sinn und Zweck vom Roboternetz. Es gab Zeiten hier im Forum, da haben sich Neulinge über die nette und Informative Hilfe hier im Netz bedankt! Sie hatten darum soviel Freuden im Roboternetz weil die Leute nicht so waren wie in anderen Foren, dort wo man nur noch blöde Antworten bekommt. Das ist vielleicht auch der Grund das nur noch Anfänger Ihre Projekte vorstellen und die wirklich guten Roboterbauer Ihre Bots lieber nicht einstellen da nur noch rumgenörgelt und gemeckert wird, anstatt konstruktive Beiträge abzuliefern. Baut doch erst mal selber einen eigenen Roboter ohne Bausatz, steckt viel Arbeit rein und dann werdet Ihr wo ihr gerade voller Stolz euren Roboter hier vorstellt nur noch schwach angeredet! Dieses Verhalten ist mir mittlerweile sehr oft aufgefallen, vor allem bei recht gut Konstruierten Robotern!
Nibo ist zwar wirklich nix für den Einsteiger, wobei Einsteiger nicht immer die Altersklasse 12 sein muss! Einsteiger sind auch die Leute die nebenbei ein Studium oder eine Ausbildung machen und sich zuvor mehr mit Elektronik oder Mechanik beschäftigt haben. Wer grundsätzlich null Ahnung hat und evtl. nur zwei linke Hände mit lauter Daumen dran besitzt, sollte eher die Finger davon lassen bevor er sich, oder andere verletzt!
Die Robotik ist ein Zusammenspiel von Mechanik, Elektronik und Programmierarbeit. Wer sich nur mit einer der oben genannten Sache beschäftigen will sollte lieber erst gar nicht damit anfangen! Oder zumindest nicht auf anderen rum hacken weil sie Rechtschreibfehler oder evtl. einen Hammer in der Anleitung vergessen haben. (Keine Anspielung auf eine bestimmte Person!)
An euere Stelle würde ich lieber schreiben was euch beim Bausatz noch alles wichtig wäre und was die C Bibliothek enthalten sollte und welche Beispiele euch Interessieren.
Das Video ist auf jedenfall schon mal gut gemacht und Nibo fährt sauber durch die Wohnung, nicht schlecht!
Lasst euch diese Zeilen mal durch den Kopf gehen ohne gleich auf meiner Aussage rumzuhacken!
PS: Wer Rechtschreibfehler findet kann sie gerne behalten!
Gruß Ulli
Trotz aller Sachlichkeit aber Thread nicht aus Promotiongründen "nach oben posten", so herausragend ist dann das ganze auch wieder nicht. Der Preis und Leistung ist aber schon ok denke ich, nur die Zielgruppe scheint mir etwas verfehlt. Für Anfänger weniger geeignet und für Profis nicht so richtig reizvoll. Also den Thread werde ich wegen dem versteckten "Promotionansatz" beobachten ;-) Also nicht übertreiben!
Vielleicht sollten die engagierten Bastler im Roboternetz mal einen Thread öffnen und ihren virtuellen Wunschroboter konstruieren. So könnte dann was richtig interessantes entstehen, wobei man alle natürlich nie wirklich zufriedenstellen kann.
Frank
admin
Genau Frank!
für Quereinsteiger aus der Elektronik oder Mechanik bestens geeignet aber nicht für nen Schüler oder kompletten Anfänger der noch gar keine Erfahrung besitzt.
Ich kenne Nibo zwar nicht, aber ich denke das man in Zusammenarbeit noch viel verbessern kann, das geht natürlich nur mit sachlichen Beiträgen und guter Umgangsform unter den Usern!
Hallo
Wenn sich mal jemand die Mühe machen würde und meinen ersten Beitrag mal lesen würde, dann könnte er dort einige Aussagen finden, die später im Thread von anderen bestätigt wurden. Mich störte die Summe des Unsinns und Floskeln wie "Einsteigergeeigenet" und "Schüler und Studenten technische Inhalte vermitteln". Zusammen mit den für eine Anleitung in dieser Preisklasse zu vielen Rechtschreibfehlern war dies eben der Grund, warum ich den Roboter für mich ablehnte. Aber inzwischen seid ihr ja auch meiner Meinung:Zitat:
Oder zumindest nicht auf anderen rum hacken weil sie Rechtschreibfehler oder evtl. einen Hammer in der Anleitung vergessen haben. (Keine Anspielung auf eine bestimmte Person!)
Na also, das lese ich eindeutig als Lob. Warum eine 4-Quatrantenregelung in Verbindung mit PWM energiesparend ist, weis ich zwar immer noch nicht, aber der Anbieter scheint darauf ja auch keinen Wert zu legen. Aber ich glaube, dass will ich inzwischen auch gar nicht mehr wissen. O:)Zitat:
.... Wer sich darüber im Klaren ist und die entsprechenden Kenntnisse und Fähigkeiten besitzt, erwirbt viel Roboter für wenig Geld und hat sicher seinen Spass mit dem nibo.
Gruß
mic
Beim energiesparren wird er nur den PWM meinen, anstatt die Energie über einen Widerstand zu verbraten. PWM ist zwar gängig aber so extrem falsch finde ich den Satz jetzt nicht!
Naja so unrecht hat er dabei ja auch nicht!
Früher hat man so einen Antrieb über Transistoren, Relais oder Lastwiderstände gemacht. Heute macht man das über eine MOSFET H-Brücke die schon energiesparrend im gegensatz du den alten Schaltungen ist. Setzt man noch die passenden MOSFETS ein, mit geringen Innenwiderstand bei Ugs = Ub kann man von energiesparrend sprechen da "fast" keine Leistung in der H-Brücke verbraten wird! PWM statt Widerstand oder Strombegrenzung zur Drehzahlanpassung über Transistoren ist dagegen "verlustfrei".
Ich hoffe ich konnte seinen Gedankengang bissl ausdeutschen...
Man sollte nicht jedes Wort auf die Goldwage legen!
Gruß Ulli
Ich lese das auch eine weile mit , und finds schade das sich hier die RN-User ein Kopf darüber machen muss wie das der Nibo-Macher wohl meint.
Das -Workwind- dazu nichts mehr sagt ist echt schade für ihn.
Und zur Rechtschreibung, eine Doku macht mehr her wenn keine Fehler drinn sind , das muss ich auch bei meinen Berichten für die Hochschule machen, da sollte es für ein Produkt was man verkaufen möchte Pflich sein.
Was würdest du machen wenn, die ein Gerät von nem deutschen Markenhersteller kaufst und die Gebrauchsanleitung voller Fehler wäre ?
Es wirkt sich schon aufs Image aus.
Gruß
Da gebe ich dir schon recht, aber ich glaube eher das er mit den Thread Verbesserung in seiner Arbeit wollte als nur Kritisiert zu werden, oder?
Da kann man halt auch anders antworten...
Über Gebrauchanleitungen brauchen wir nicht diskutieren, da hab ich wahrscheinlich schon mehr gelesen als du glaubst und zu den Fehlern sag ich da lieber nix! Vor alle ist es in einer Anleitung vorrangig wichtig dass der Technische Inhalt stimmt!
Hallo zusammen!
Zu meinem langen Schweigen muss ich sagen, dass ich von dem Ton in diesem Forum ein bischen irritiert bin....
Aber nun zur Sache:
Die PWM Ansteuerung bei einer Motorbrücke läßt sich auf zwei Arten durchführen:
Möglichkeit A:
- Während der High-Phase schalten zwei diagonal angeordnete Transistoren
- Während der Low-Phase schaltet kein Transistor, der Induktionsstrom fliesst durch die Dioden ab.
Möglichkeit B:
- Während der High-Phase schalten zwei diagonal angeordnete Transistoren
- Während der Low-Phase schaltet zwei Transistoren nach Masse (oder V+) der Motor ist kurzgeschlossen, der Induktionsstrom fliesst durch die beiden Transistoren im Kreis.
Die Möglichkeit A hat folgende Nachteile:
- Die Magnetische Feldenergie pendelt zwischen Ankerinduktivität und Batterie mit der Frequenz der PWM-Ansteuerung und gegen die Versorgungsspannung hin und her.
- Bei hohen PWM Frequenzen bricht das Drehmoment ein, insbesondere bei kleinen "High-Anteilen". Dadurch ist die Regelbarkeit des Motors erschwert.
Die Möglichkeit B hat folgende Vorteile:
- Der Strom pendelt nicht hin und her, sondern fliesst im Kreis, daher ist der Wirkungsgrad (es geht mir hierbei nicht um die Umwelt) höher
- Die PWM-Frequenz kann über dem hörbaren Bereich liegen, dadurch zwitschert der Motor nicht
- Der Motor läßt sich einfacher mit einem PID Regler regeln, da die mittlere Motorspannung proportional zum PWM Anteil ist.
Natürlich interessieren mich auch die Nachteile von Version B und die Vorteile von Version A, ich kenne sie aber nicht...
Für den Nibo habe ich Version B gewählt (und die Benutzung im Motor-Controller implementiert), auch der Asuro kann mit der Version B angesteuert werden.
In vielen Schaltungen die den L293D verwenden, wird der Motor jedoch nach Möglichkeit A angesteuert, da sie sich diese leichter implementieren läßt.
Die Vorteile der Möglichkeit B werden auch in vielen Artikeln über den L293D nicht erwähnt. Ich wollte mit meinem Hinweis auf eine bessere Energieausnutzung einen (leicht zu verstehenden) Vorteil der Ansteuerung nach Möglichkeit B hervorheben - anscheinlich ist mir das jedoch nicht gelungen... :-(
Ansonsten würde ich sagen:
Der RP6 ist auch ein guter Roboter, Konkurenz belebt das Geschäft und fördert insbesondere die Innovation... . Sich hier im Forum gegenseitig mit Worten anzugreifen bringt die Robotik nicht weiter - und das wollen wir doch alle!
Schönen Gruß,
Nils Springob
Das Bild vom Antrieb hat übrigens nur 594 Pixel Breite.Zitat:
Bilder mit mehr als 600 Pixel Breite ...
Dem kann ich weitgehend zustimmen. Das Interessante am Nibo ist der große Speicher des ATmega128 und die Unterstützung durch die beiden ATtiny44 (Motorcontroller, IR-Controller). Das könnte - vom ASURO kommend - interessante Perspektiven eröffnen.Zitat:
für Quereinsteiger aus der Elektronik oder Mechanik bestens geeignet aber nicht für nen Schüler oder kompletten Anfänger der noch gar keine Erfahrung besitzt.
Das eine ja, andere waren fast 800 Pixel breit. Angenehmer sind Bilder bis 500 Pixel, einfach mal nach dem Posting den Thread anschaun und gesunden Menschenverstand zum beurteilen einsetzen - dann brauchen wir nicht über Pixel zu diskutieren ;-)Zitat:
Zitat von ehenkes
Testsoftware und über den ATmega128 programmierte Firmware für die beiden ATtiny44 steht nun incl. Beschreibung zur Verfügung:
http://nibo.editthis.info/wiki/Software
Das von mir getestete System funktionierte wie beschrieben.
Passende C-Bibliothek wird von nicai-systems zur Verfügung gestellt: http://sourceforge.net/projects/nibo/
Die Bibliothek ist logisch und klar aufgebaut, also ein brauchbares Fundament.
Beim Verbinden des Atmel STK500 Starter Kit mit dem 6-Pin-ISP-Stecker des Nibo muss man auf die korrekte Ausrichtung des Steckers achten, da man diesen drehsymmetrisch falsch einstecken kann. Hier die korrekte Verbindung, falls das jemand machen will:
Bild hier
@steveLB: Ich stimme dir ja in vielen zu nur bei folgendem Punkt nicht:
Es gibt genügend Institutionen bei der perfekte Rechtschreibung, Gramatik und Form gefordert werden aber ich finde man kann auch mal drüberweg sehen wenn der Macher eines guten Produktes hier nicht soviel Wert drauf legt als auf das Produkt selbst. Mir wäre es Schnurz wieviel Rechtschreibfehler in einer Produktbeschreibung sind solange die gut verständlich und sachlich ok ist. Letzteres kann ich hier nicht beurteilen da ich diese nicht gelesen habe. Aber ich finde es unangemessen eine aufwenige Arbeit wegen ein paar Schreibfehlern nieder zu reden. In meinen Dokus sind garantiert auch genug drin, einfach weil in erster Linie das basteln das Hobby und die Stärke ist und nicht das geschreibe. Ich weiss das jetzt innerlich einige aufschrein - aber wir sollten diesen Thread nicht noch weiter mit Grundsatzdiskussionen zerstören. Jedenfalls sehe ich es nicht gerne wenn im Roboternetz wegen Schreibfehlern gelästert wird - so nörgelig soll es hier nun doch ncht werden, das sollen andere Foren übernehmen. Was nicht heißt das ich es nicht schön finde wenn zumindest die Betreffs fehlerfrei im Forum stehen ;-)Zitat:
Zitat von steveLB
Gruß Frank
Zitat:
Und zur Rechtschreibung, eine Doku macht mehr her wenn keine Fehler drinn sind ,...
... da sollte es für ein Produkt was man verkaufen möchte Pflich sein.
das ich auch fehler mache ist klar , danke robo.fr :D
@ Frank
ist meine meinung , ich mach da keinen nieder weger der rechtschreibung, wollt damit nur sagen das man da achten soll, und das rechtschreibprogramm von Word kann man ja mal drüber lassen.
ich hab seine anleitung auch noch nicht gelesen, hatte keine zeit, da ich bis heute prüfungen hatte :)
und *JUHU* sie sind rum *freu*
<-- macht Ferien
EDIT : ich weiß auch das Basteler wie wir lieber ihr Wunderwerk schnell und mit vielen Details und vor allem Inhalt presentieren , da bleibt die Rechtschreibung mal auf der Strecke, ich mach das auch so , nur wenn ich etwas abgeben muss ( für eine Note, oder um es zu Verkaufen) dann wird die Rechtschreibung mal eingeschaltet.
Gruß
Jetzt hört doch endlich mit der Rechtschreibung auf. ;) Diese Diskussionen existieren in jedem Forum bis zum Erbrechen.
... und was die Programmierung angeht, da sieht das bestens aus. Die C-Bibliothek ist klasse!
extra für ehenkes : Rechtschreibung *gg*
habs jetzt die Doku überflogen, sieht sauber aus , denk ich könnt den auch Aufbauen *fg*
Gruß
Die Dokumentation ist noch im Fluss. Meine Erfahrungen und Probleme beim Aufbau und Testen - und meine Rechtschreibkünste - lasse ich dem Entwickler selbstverständlich zukommen, was sich in einer weiteren Verbesserung der Dokumentation nieder schlagen wird. Wichtig ist auch das wiki zum Nibo, das ständig wächst und gedeiht. Wenn man mit dem ASURO beginnt und sich damit einige Erfahrung aneignet, kann man sich auch an den Nibo heran trauen. Die Struktur der Programmbibliothek in C wird euch sicher gefallen, ist sehr ordentlich.
Allerdings kämpfe ich momentan noch mit zwei Punkten in der Elektronik. Die Odometrie und die Abgrundsensoren funktionieren nicht wie erwartet. Nun ist die Frage, ob es an der Elektronik oder dem Testprogramm liegt. Da fehlen einfach noch die Erfahrungen. Momentan muss man Anfängern daher vom Nibo abraten, bis genügend Erfahrungen mit Problemfällen und/oder Abweichungen vorliegen. Das System ist komplex.
EDIT1:
Thema Odometrie ist gelöst. Es war eine schlechte Lötstelle am 10-Pin-Wannenstecker. Darauf kommt man allerdings nicht so schnell, weil das 10-Pin->2*5-Pin-Kabelsystem kompliziert ist und man den Fehler eher dort vermutet.
Man sollte nun 20 (= 4 Löcher * 5-fach Untersetzung) Zählimpulse pro Radumdrehung beobachten können. Bei den mitgelieferten Gummirädern mit 37 mm Durchmesser entspricht dies 3,1416 * 37 mm / 20 Zähler = 5,8 mm / Zähler (c't-Bot: 3 mm/Zähler, RP6: 0.25 mm/Zähler ).
EDIT2:
Thema Abgrundsensoren (CNY70) vorne rechts/links ist hoffentlich auch gelöst. Problem war offensichtlich ein Kurzschluss der Beinchen der Liniensensoren (unter der Platine, Beinchen oben eingelötet und abgezwickt) gegen die Rückseite des darüber platzierten Spannungsreglers 7805. Da fehlt noch eine professionelle elektrische Isolierung! Ich hatte vorsichtshalber Isolierband aufgeklebt, aber das wird sicher leicht durchstoßen von abgezwickten Beinchen. Wäre z.B. Nachlöten notwendig geworden, hätte ich Nibo wieder mühsam "zerpflücken" müssen. Das ist beim Aufbau/Testen ein konstruktiver Schwachpunkt des Nibo, weil man nicht mehr an die Lötpunkte der Liniensensoren heran kommt. Dieses Thema muss in der Dokumentation ausführlicher besprochen werden und eine passende mechanisch stabile Isolation sollte mitgeliefert werden.
Seit heute morgen steht die erste offizielle Bibliothek (C/C++) für den Roboterbausatz Nibo zum Download bereit:
https://sourceforge.net/project/show...kage_id=239101
Zur Beachtung: Mit AVR Studio (kostenlos bei Atmel) Version 4.12 unbedingt das Service Pack verwenden (ansonsten hängt sich der Compiler/Linker aus unerklärlichen Gründen auf), noch besser ist es, die aktuelle Version 4.13 einzusetzen. Diese zeigt zusätzlich den durch das Programm belegten Speicherplatz im ATmega128 an.
Zum Eingewöhnen eine erste Firmware für den Nibo:
Die sechs Status-LEDs sind von 0 bis 5 nummeriert, wie man es analog einem C-Array erwartet. Solche Feinheiten finde ich z.B. wichtig, damit die Programmierung intuitiv auf Anhieb gelingt. Das helle vorne sind die beiden "Scheinwerfer" ( vgl. http://www.nicai-systems.de/images/niboAtNight_320.jpg ), die die daneben liegenden Status-LEDs im Dunkeln überstrahlen.Code:#include <avr/interrupt.h>
#include "nibo/niboconfig.h"
#include "nibo/delay.h"
#include "nibo/pwm.h"
#include "nibo/display.h"
#include "nibo/bot.h"
#include "nibo/gfx.h"
#include "nibo/bot.h"
#include "nibo/gfx.h"
#include "nibo/leds.h"
int main()
{
sei(); // enable interrupts
bot_init();
leds_init();
pwm_init();
display_init();
gfx_init();
leds_set_displaylight(600);
gfx_move(10,10);
gfx_print_text("Nibo sagt:", 0);
gfx_move(10,30);
gfx_print_text("Hallo Welt!", 0);
int i,j;
for(i=0;i<10;++i)
{
for(j=0;j<6;++j)
{
leds_set_status(LEDS_RED,j);
delay(500);
}
leds_set_headlights(256);
for(j=0;j<6;++j)
{
leds_set_status(LEDS_ORANGE,j);
delay(500);
}
leds_set_headlights(512);
for(j=0;j<6;++j)
{
leds_set_status(LEDS_GREEN,j);
delay(500);
}
leds_set_headlights(1024);
}
while(1);
return 0;
}
Bild hier
Ich kann den Nibo nur mit Grafikdisplay empfehlen. Gerade die Initializer-Software, die die beiden ATtiny44 mit Firmware und den ATmega128 mit Testsoftware versorgt, visualisiert für erste Prüfungen nach dem Aufbauen wichtige Messdaten zu Odometrie, Abgrund- und Liniensensoren, fünffache IR-Abstandsmessung (nach vorne und zur Seite) und RC5-Codes.
Für wenige Daten ist dies einfach bequemer und autonomer als die IR-Kopplung an einen PC mit Terminal-Software.
Was mir gut gefällt, ist die einfache Textausgabe auf dem internen "Terminal". Das ist anfängergerecht. :)
Man kann die Funktionen gfx_move(...) und gfx_print_text(...) auch in eine WinAPI-analoge Funktion umbauen:
Das erleichtert bei mehrzeiligen Ausgaben die Übersicht im Programm.Code:void textout(int x, int y, char* str, int ft)
{
gfx_move(x,y);
gfx_print_text(str,ft);
}
Eine detaillierte Untersuchung der Programmiermöglichkeiten werde ich hier beschreiben: http://www.henkessoft.de/Roboter/Nibo.htm
Hier noch ein Beispiel zur Ausgabe der Batteriespannung:
Beim Flashen mit dem STK500 sieht man mit diesem Programm die von diesem Board anliegende Spannung, da das Programm nach dem Flashen sofort startet: 4,70 VoltCode:#include <avr/interrupt.h>
#include "nibo/niboconfig.h"
#include "nibo/delay.h"
#include "nibo/pwm.h"
#include "nibo/display.h"
#include "nibo/leds.h"
#include "nibo/bot.h"
#include "nibo/gfx.h"
#include "nibo/bot.h"
/*
float round(float zahl, int stellen)
{
float v[] = { 1, 10, 1e2, 1e3, 1e4 };
return floor(zahl * v[stellen] + 0.5) / v[stellen];
}
*/
void float2string(float value, int decimal, char* valuestring)
{
int neg = 0; char tempstr[20];
int i = 0; int j = 0; int c; long int val1, val2;
char* tempstring;
tempstring = valuestring;
if (value < 0){ neg = 1; value = -value; }
for (j=0; j < decimal; j++) {value = value * 10;}
val1 = (value * 2);
val2 = (val1 / 2) + (val1 % 2);
while (val2 !=0){
if ((decimal > 0) && (i == decimal)){
tempstr[i] = (char)(0x2E);
i++;
}
else{
c = (val2 % 10);
tempstr[i] = (char) (c + 0x30);
val2 = val2 / 10;
i++;
}
}
if (neg){
*tempstring = '-';
tempstring++;
}
i--;
for (;i > -1;i--){
*tempstring = tempstr[i];
tempstring++;
}
*tempstring = '\0';
}
float SupplyVoltage(void)
{
bot_update();
return(0.0166 * bot_supply - 1.19);
}
void textout(int x, int y, char* str, int ft)
{
gfx_move(x,y);
gfx_print_text(str,ft);
}
void Init(void)
{
sei(); // enable interrupts
bot_init();
leds_init();
pwm_init();
display_init();
gfx_init();
}
int main()
{
Init();
leds_set_displaylight(1000);
float Ubatt = SupplyVoltage();
char text[6];
float2string(Ubatt,2,text);
textout(4,10,"Versorgungsspannung:",0);
textout(4,24,text,0);
textout(60,24,"Volt",0);
while(1);
return 0;
}
Die Spannung des Nibo liegt mit geladenen Akkus über 10 Volt. [/code]
Würde mich wirklich freuen, wenn mehr Nibo-Besitzer sich hier einfinden würden. Sowohl die Hardware als auch bereits die allererste C/C++-Bibliothek ist eine hervorragende Basis für eigene Entwicklungen, und der ATmega128 bietet ausreichend Platz und I/O-Ports. Die "Dreckarbeit" (Motor steuern, Kollision vermeiden) erledigen ja bereits die beiden ATtiny44, mit denen der Hauptprozessor über I²C kommuniziert. :)Zitat:
... hab jetzt die Doku überflogen, sieht sauber aus, denk' ich könnt' den auch aufbauen. *fg*
Als kleines Beispiel (noch nicht perfekt) für die Motorsteuerung:
Im Gegensatz zu seinem kleinen Bruder fällt Nibo das Geradeausfahren leicht. Der MOTCO nimmt dem Hauptprozessor delegierbare Regelungs-Arbeit (Geschwindigkeit, Richtung) gerne ab.Code:#include <avr/interrupt.h>
#include "nibo/niboconfig.h"
#include "nibo/delay.h"
#include "nibo/pwm.h"
#include "nibo/display.h"
#include "nibo/bot.h"
#include "nibo/gfx.h"
#include "nibo/bot.h"
#include "nibo/gfx.h"
#include "nibo/leds.h"
#include "nibo/motco.h"
void textout(int x, int y, char* str, int ft)
{
gfx_move(x,y);
gfx_print_text(str,ft);
}
void Go(int dist, int cm_pro_sec)
{
const float TICKS_PER_CM = 1.75f;
motco_resetOdometry(0,0);
motco_update();
int limit = dist * TICKS_PER_CM;
int pwm = cm_pro_sec * 80;
if (pwm > 1024) pwm = 1024;
if (pwm < -1024) pwm = -1024;
motco_setPWM(pwm,pwm);
motco_setSpeed(cm_pro_sec * TICKS_PER_CM , cm_pro_sec * TICKS_PER_CM);
motco_update();
delay(3000); //TODO: Verzögerung muss noch weg
do
{
motco_update(); /* fährt brav geradeaus */
}
while(motco_ticks_l < limit);
}
int main()
{
sei(); // enable interrupts
bot_init();
leds_init();
pwm_init();
display_init();
gfx_init();
leds_set_displaylight(800);
textout(10,10,"Nibo meldet:",0);
textout(10,24,"Motor an!",0);
textout(10,38,"Licht an!",0);
leds_set_headlights(512);
int i,j;
for(i=1;i<=6;++i)
{
for(j=0;j<i;++j)
leds_set_status(LEDS_GREEN,j);
Go(50,10*i);
}
leds_set_headlights(0);
motco_stop();
motco_update();
for(j=0;j<6;++j)
leds_set_status(LEDS_OFF,j);
textout(10,24,"Motor aus!",0);
textout(10,38,"Licht aus!",0);
while(1);
return 0;
}
Hier der Video-Link (2,7 MB) zum Programm: http://www.henkessoft.de/Roboter/Bilder/Nibo.wmv
Die Abstandsmessung mittels IR-Sensoren wird prinzipiell in diesem Programm gezeigt:
Allerdings nimmt Nibo bei mir selbst den Boden noch als Hindernis wahr. Das leuchtet mir konstruktiv noch nicht richtig ein.Code:#include <stdlib.h>
#include <avr/interrupt.h>
#include "nibo/niboconfig.h"
#include "nibo/delay.h"
#include "nibo/pwm.h"
#include "nibo/display.h"
#include "nibo/leds.h"
#include "nibo/bot.h"
#include "nibo/gfx.h"
#include "nibo/irco.h"
void float2string(float value, int decimal, char* valuestring)
{
//... siehe oben!
}
float SupplyVoltage(void)
{
bot_update();
return(0.0166 * bot_supply - 1.19);
}
void textout(int x, int y, char* str, int ft)
{
gfx_move(x,y);
gfx_print_text(str,ft);
}
void Init(void)
{
sei(); // enable interrupts
bot_init();
leds_init();
pwm_init();
display_init();
gfx_init();
}
int main()
{
Init();
leds_set_displaylight(1000);
while(1)
{
float Ubatt = SupplyVoltage();
char text[6];
float2string(Ubatt,2,text);
textout( 0,0,text, 0);
textout(35,0,"Volt",0);
irco_update();
irco_startMeasure();
irco_update();
char irco_string[5][5];
int i;
for(i=0; i<5; ++i)
{
textout(i*21,8," ",0); //löschen
}
for(i=0; i<5; ++i)
{
itoa(irco_distance[i],irco_string[i],10);
textout(i*21,8,irco_string[i],0);
}
delay(200);
}
while(1);
return 0;
}
Das Prinzip ist hier beschrieben: http://nibo.editthis.info/wiki/IR-Controller
Hat jemand eine Idee, wie man die Messung optimieren kann? Das "Raumgefühl" durch Messungen in fünf Richtungen (rechts, vorne rechts, vorne mitte, vorne links, links) soll einer der Vorzüge des Nibo sein. Später können über den Erweiterungsport z.B. weitere Abstandsmessungen nach hinten oder für die berühmten Bürostühle hinzu kommen.
Mit diesem Programm kann man die gesamte Sensorik des Nibo in Ruhe analysieren (Batteriespannung, IR-Abstand, Abgrundsensoren, Liniensensoren)
Damit bewegt er sich so, dass er Hindernissen ausweicht:Code:#include <stdlib.h>
#include <avr/interrupt.h>
#include "nibo/niboconfig.h"
#include "nibo/iodefs.h"
#include "nibo/delay.h"
#include "nibo/adc.h"
#include "nibo/pwm.h"
#include "nibo/i2cmaster.h"
#include "nibo/display.h"
#include "nibo/bot.h"
#include "nibo/leds.h"
#include "nibo/gfx.h"
#include "nibo/irco.h"
#include "nibo/motco.h"
#include "nibo/floor.h"
void Init(void)
{
sei(); // enable interrupts
i2c_init();
pwm_init();
display_init();
bot_init();
leds_init();
floor_init();
gfx_init();
}
void float2string(float value, int decimal, char* valuestring)
{
int neg = 0; char tempstr[20];
int i = 0; int j = 0; int c; long int val1, val2;
char* tempstring;
tempstring = valuestring;
if (value < 0){ neg = 1; value = -value; }
for (j=0; j < decimal; j++) {value = value * 10;}
val1 = (value * 2);
val2 = (val1 / 2) + (val1 % 2);
while (val2 !=0){
if ((decimal > 0) && (i == decimal)){
tempstr[i] = (char)(0x2E);
i++;
}
else{
c = (val2 % 10);
tempstr[i] = (char) (c + 0x30);
val2 = val2 / 10;
i++;
}
}
if (neg){
*tempstring = '-';
tempstring++;
}
i--;
for (;i > -1;i--){
*tempstring = tempstr[i];
tempstring++;
}
*tempstring = '\0';
}
float SupplyVoltage(void)
{
bot_update();
return(0.0166 * bot_supply - 1.19);
}
void textout(int x, int y, char* str, int ft)
{
gfx_move(x,y);
gfx_print_text(str,ft);
}
int main()
{
Init();
leds_set_displaylight(1000);
floor_enable_ir();
while(1)
{
float Ubatt = SupplyVoltage();
char text[6];
float2string(Ubatt,2,text);
textout( 0,0,text, 0);
textout(35,0,"Volt",0);
textout(0,8,"distance:",0);
textout(0,24,"floor:",0);
textout(0,40,"line:",0);
irco_update();
irco_startMeasure();
irco_update();
uint16_t floor_distance[2];
uint16_t line_distance[2];
floor_update();
floor_distance[0] = floor_l;
floor_distance[1] = floor_r;
line_distance[0] = line_l;
line_distance[1] = line_r;
//Strings für Display
char irco_string[5][5];
char floor_string[2][5];
char line_string[2][5];
int i;
/*
IR-Abstandssensoren
*/
for(i=0; i<5; ++i)
{
textout(i*21,16," ",0); //löschen
}
for(i=0; i<5; ++i)
{
itoa(irco_distance[i],irco_string[i],10);
textout(i*21,16,irco_string[i],0);
}
/*
IR-Floorsensoren (Abgrunderkennung)
*/
for(i=0; i<2; ++i)
{
textout(i*28,32," ",0); //löschen
}
for(i=0; i<2; ++i)
{
itoa(floor_distance[i],floor_string[i],10);
textout(i*28,32,floor_string[i],0);
}
/*
IR-Liniensensoren
*/
for(i=0; i<2; ++i)
{
textout(i*28,48," ",0); //löschen
}
for(i=0; i<2; ++i)
{
itoa(line_distance[i],line_string[i],10);
textout(i*28,48,line_string[i],0);
}
delay(100);
}
while(1);
return 0;
}
Code:#include <stdlib.h>
#include <avr/interrupt.h>
#include "nibo/niboconfig.h"
#include "nibo/iodefs.h"
#include "nibo/delay.h"
#include "nibo/adc.h"
#include "nibo/pwm.h"
#include "nibo/i2cmaster.h"
#include "nibo/display.h"
#include "nibo/bot.h"
#include "nibo/leds.h"
#include "nibo/gfx.h"
#include "nibo/irco.h"
#include "nibo/motco.h"
#include "nibo/floor.h"
#define LINKS 0
#define VORNE_LINKS 1
#define VORNE 2
#define VORNE_RECHTS 3
#define RECHTS 4
void Init()
{
sei(); // enable interrupts
i2c_init();
pwm_init();
display_init();
bot_init();
leds_init();
floor_init();
gfx_init();
}
void float2string(float value, int decimal, char* valuestring);
float SupplyVoltage(void)
{
bot_update();
return(0.0166 * bot_supply - 1.19);
}
void textout(int x, int y, char* str, int ft)
{
gfx_move(x,y);
gfx_print_text(str,ft);
}
int main()
{
Init();
// Kollisionsvermeidung vorbereiten
uint16_t Vektor[5][2]; // Einheitsvektoren (*10) [0] ist x- und [1] ist y-Wert
Vektor[0][0] = -10; // LINKS x
Vektor[0][1] = 0; // LINKS y
Vektor[1][0] = -7; // VORNE_LINKS x
Vektor[1][1] = 7; // VORNE_LINKS y
Vektor[2][0] = 0; // VORNE x
Vektor[2][1] = 10; // VORNE y
Vektor[3][0] = 7; // VORNE_RECHTS x
Vektor[3][1] = 7; // VORNE_RECHTS y
Vektor[4][0] = 10; // RECHTS x
Vektor[4][1] = 0; // RECHTS y
uint16_t VektorMalSensor[5][2]; // Sensorwert * Einheitsvektor (*10)
uint16_t VektorMalSensorSumme[2]; // Sensorschwerpunkt (x,y) für Auswertung
// Vorbereitungen
leds_set_displaylight(1000);
leds_set_headlights(512);
floor_enable_ir();
motco_setPWM(600,600);
motco_setSpeed(25,25);
// fixe Display-Anzeigen
textout(35,0,"Volt", 0);
textout(0, 8,"distance:", 0);
textout(0,24,"floor:", 0);
textout(0,40,"line:", 0);
// Hauptschleife
while(1)
{
// Akkuspannung anzeigen
float Ubatt = SupplyVoltage();
char text[6];
float2string(Ubatt,2,text);
textout(0,0," ",0); // 5 Zeichen löschen
textout(0,0,text, 0);
// Abstandsmessung Raumgefühl
irco_update();
irco_startMeasure();
irco_update();
// Floor
uint16_t floor_distance[2];
uint16_t line_distance[2];
// Abstandsmessung Floor
floor_update();
floor_distance[0] = floor_l;
floor_distance[1] = floor_r;
line_distance[0] = line_l;
line_distance[1] = line_r;
//Strings für Display
char irco_string[5][5];
char floor_string[2][5];
char line_string[2][5];
// Laufvariablen
int i,j;
/*
IR-Abstandssensoren
*/
for(i=0; i<5; ++i)
textout(i*21,16," ",0); //löschen
for(i=0; i<5; ++i)
{
itoa(irco_distance[i],irco_string[i],10);
textout(i*21,16,irco_string[i],0);
}
/*
IR-Floorsensoren (Abgrunderkennung)
*/
for(i=0; i<2; ++i)
textout(i*28,32," ",0); //löschen
for(i=0; i<2; ++i)
{
itoa(floor_distance[i],floor_string[i],10);
textout(i*28,32,floor_string[i],0);
}
/*
IR-Liniensensoren
*/
for(i=0; i<2; ++i)
textout(i*28,48," ",0); //löschen
for(i=0; i<2; ++i)
{
itoa(line_distance[i],line_string[i],10);
textout(i*28,48,line_string[i],0);
}
/*
MOTCO
Mathematische Methode "x/y-Schwerpunkt der Sensorvektoren bilden":
(Einheitsvektoren * 10) * Sensorwert (0-255), davon Summe bilden
VektorMalSensorSumme[...] 0 ist x-Wert und 1 ist y-Wert
Blockade: y kann maximal 6120 groß werden (vl, v, vr 255)
Richtung: x kann maximal -4335 (Hindernis links) bzw. +4335 (H. rechts) werden (l, vl 255 bzw. r, vr 255)
*/
VektorMalSensorSumme[0] = 0; // x-Wert
VektorMalSensorSumme[1] = 0; // y-Wert
for (i=0; i<5; ++i)
{
for (j=0; j<2; ++j)
{
VektorMalSensor[i][j] = Vektor[i][j] * irco_distance[i];
VektorMalSensorSumme[j] += VektorMalSensor[i][j];
}
}
// Reaktion auf VektorMalSensorSumme[...] (x- und y-Wert)
if(VektorMalSensorSumme[1] >= 4590)
{
motco_setSpeed(-25,-25); //rückwärts fahren
}
else if( (VektorMalSensorSumme[1] < 4900) && (VektorMalSensorSumme[1] >= 3060) )
{
if(VektorMalSensorSumme[0] < -2500) // Hindernis links
motco_setSpeed(25,-25);
else if ( (VektorMalSensorSumme[0] >= -2500) && (VektorMalSensorSumme[0] <= 2500) ) // kein Hindernis
motco_setSpeed(25,25);
else // Hindernis rechts
motco_setSpeed(-25,25);
}
else
{
motco_setSpeed(30,30);
}
motco_update();
}
while(1);
return 0;
}
// Hilfsfunktionen
void float2string(float value, int decimal, char* valuestring)
{
int neg = 0; char tempstr[20];
int i = 0; int j = 0; int c; long int val1, val2;
char* tempstring;
tempstring = valuestring;
if (value < 0){ neg = 1; value = -value; }
for (j=0; j < decimal; j++) {value = value * 10;}
val1 = (value * 2);
val2 = (val1 / 2) + (val1 % 2);
while (val2 !=0){
if ((decimal > 0) && (i == decimal)){
tempstr[i] = (char)(0x2E);
i++;
}
else{
c = (val2 % 10);
tempstr[i] = (char) (c + 0x30);
val2 = val2 / 10;
i++;
}
}
if (neg){
*tempstring = '-';
tempstring++;
}
i--;
for (;i > -1;i--){
*tempstring = tempstr[i];
tempstring++;
}
*tempstring = '\0';
}
Hallo, ich habe mir auch einen Nibo gekauft und muss ihn nun erstmal zusammenlöten....
In einem anderen Faden
https://www.roboternetz.de/phpBB2/vi...=302266#302266
wird das MSRS diskutiert. Wäre es nicht gut, den Nibo als Hardwarebasis zu verwenden?
Gruß
Lisbeth
Wenn Du Fragen zum Zusammenbau hast, die versuche ich gerne zu beantworten. Kritisch ist das 10->2*5-Kabel der Odometrie und die Rückseite des 7805 muss man gut isolieren (2 Lagen Isolierband, Kurzschlussgefahr mit CNY70-Beinchen). Es gibt da schon einige Punkte zu beachten. Die Platine ist nicht ganz einfach gestrickt, also kein ASURO.
Bezüglich des MSRS bin ich mir noch nicht sicher. Es ist für den Nibo noch zu früh, da die Firmware/Software des Nibo noch in der Entwicklungsphase ist. Wenn hier Stabilität hergestellt ist, könnte man das Thema mal angehen. Auf jeden Fall können wir dann endlich Programme tauschen, etc. :)
Ich dachte, gerade wenn die Plattform noch frisch ist und an der Firmware gearbeitet wird, ist MSRS ein Thema (parallel und nicht sequentiell arbeiten!).
Nibo ist mit 128k doch auch ein guter Kandidat für AI, oder?
Ansonsten verlief der Tag durchaus schlecht: Die Bestückung haben wir nach 10 eingelöteten Kondensatoren gefrustet abgebrochen, da der Lötzinn regelrecht abgestossen wurde!! :cry:
Keine Ahnung, warum. Mit dem gleichen Equipment haben wir den Asuro problemlos zusammengelötet!
Gruß
Lisbeth
Zu MSRS:
Stellungnahme des Entwicklers zu diesem Thema am 04.07.2007:
"In das Robotics Studio bin ich leider momentan nicht eingearbeitet, aber
ich würde es auch nicht ausschließen dafür eine Portierung zu
entwickeln. Ansonsten werden alle Quelltexte von mir unter Open-Source
Lizenzen bereit gestellt, sodass eine Anbindung an das Robotics Studio
auch durch andere erfolgen kann."
Zur Lötausrüstung:
Nibo ist kein ASURO. Die Platine ist deutlich filigraner und kann nur mit feiner Spitze und richtiger Temperatur mit gutem Lot gelötet werden. Ohne Löterfahrung geht da nichts! Ich habe ihn unter einer Leuchtlupe gelötet und war froh, als es geschafft war. Nur eine kalte Lötstelle am 10-Pin-Wannenstecker und ein Kurzschluss zwischen 7805 und CNY70.
Der ASURO ist ein Kinderspiel dagegen. Damit steht jetzt fest: Nibo ist definitiv kein Roboterbausatz für Anfänger! Ich dachte allerdings, dass er vom ASURO kommend als Upgrade tauglich sei. Ich habe allerdings recht viel Löterfahrung aus Serienfertigungen in den letzten Jahren.
Leuchtlupe, feine Spitze und richtige Temperatur:
Nix davon steht in der Anleitung zum Zusammenbau!
Die (Löt-)Anleitung beim Asuro war dagegen gut!
Für Gelegenheitslöter wie uns (nach 20 Jahren mal wieder nach dem NDR-Computer (kennt den noch wer?)) ist Nibo wohl nicht zu stemmen? Oder?
Gruß
Lisbeth
Die ASURO-Platine ist grob gegen die des Nibo, das habe ich schon mehrfach hier geschrieben, also nichts für Lötanfänger!
Die Leuchtlupe brauche ich persönlich, weil ich 51 bin, trotz Brille, sonst sehe ich die feinen Bahnen der Nibo-Platine nicht und schmelze alles zusammen, also mein Problem. Die richtige Temperatur (regelbare Lötstation) und das richtige Lötzinn (fein) ist wichtig. Man sollte auch Entlötlitze greifbar haben.
Bitte nicht aufgeben! Das ist zu schaffen. :)
Weller Lötstation WS50 ist regelbar
Lötzinn: Was ist "fein"? Ich habe HS10 mit Durchmesser 1,0mm von der Firma STANNOL.
Alles falsch?
Gruß
Lisbeth
1,0 mm ist meines Erachtens o.k. (Doku empfiehlt 0,5 mm). Daran liegt es sicher nicht, denn das habe ich auch verwendet (privat verwende ich noch bleihaltiges Lötzinn, Sn 60 Pb 38 Cu 2). Temperatur hatte ich eher hoch (350-370°C, bei Steckern 400°C) eingestellt, schnell mit wenig Lot gelötet. Weller ist doch auch ein Qualitätsname. Nur Mut! Das wird schon.
Quelle: http://www.cologne-hardware.de/grund...n/bleifrei.htmZitat:
Der Schmelzpunkt von bleifreiem Lot ist 20 °C bis 45 °C höher als der Schmelzpunkt von bleihaltigen Lot , konsequenterweise muß die Temperatur der Lötspitze höher eingestellt werden. Es ist allgemein üblich und auch akzeptabel, daß die Temperatur der Lötspitzen um ca. 50 °C höher als der Schmelzpunkt des Lotes eingestellt wird. Allerdings werden vielfach Lötspitzentemperaturen gewählt, die 100 °C höher sind als die Schmelztemperatur, diese Unterschiede sind von der Wärmekapazität des zu lötenden Werkstückes , der Lötstellengröße, und der Masse der Lötspitze abhängig.
Die Lötspitzentemperaturen werden bei bleihaltigem Lötzinn Sn – Pb mit ca. 340 °C gewählt und bei bleifreiem Lötzinn Sn – 0.7Cu auf ca. 370 °C eingestellt.
Löttemperaturen über 350 °C stoßen an die Grenzen für Lötstationen. Der Verschleiß von Lötspitzen steigt rapide und der Arbeitsbereich der Flußmittel wird überschritten. Oberhalb dieser Temperaturen verkohlt das Flußmittel, die Aktivität des Flußmittels verringert sich und es kommt zur Trennung von Lot und Flußmittel.
Im Nibo wiki findet man folgenden Beitrag zum Thema Löten:
http://nibo.editthis.info/wiki/L%C3%B6ten
Die Dokumenation wurde heute aktualisiert:
http://download.nicai-systems.com/ni...o_20070728.pdf
Ich habe das Antikollisionsprogramm mit dem geometrischen Sensorschwerpunkt um Gewichtungsfaktoren ergänzt, einen Speedfactor zugefügt, mit den Grenzen etwas gespielt und versucht, Schwingungen vorzubeugen. Diese Grenzen hängen auch noch von der Tageszeit (Lichteinfluss IR), evtl. auch von der Akkuspannung (Messwerte IR) ab. Nibo bewegt sich damit schon, ohne sich zu verletzen. ;-)
Er bleibt manchmal noch unter Bürostuhlbeinen hängen. Da könnte man etwas mit der Odometrie machen. Da die Räder bei glatten Böden durchdrehen, geht aber kein einfacher Vergleich, ob sich das Rad überhaupt noch dreht. Gebogene schwarze Hindernisse, die IR schlucken und nach oben reflektieren, sind logischerweise auch ein physikalisches Problem. Gute Tipps?
Code:/********************************************
* *
* N I B O - A N T I K O L L I S I O N *
* *
********************************************/
// Stand: 31.07.2007, 01:00h
// Erhard Henkes
// www.henkessoft.de
// Geometrischer Sensorschwerpunkt
// Gewichtung der Sensoren
// Einfaches Ausweichen nach Grenzwerten
// TODO: unter Bürostuhlbein einklemmen
// fährt im Kreis, weil er z.B. immer links ausweicht
#include <stdlib.h>
#include <avr/interrupt.h>
#include "nibo/niboconfig.h"
#include "nibo/iodefs.h"
#include "nibo/delay.h"
#include "nibo/adc.h"
#include "nibo/pwm.h"
#include "nibo/i2cmaster.h"
#include "nibo/display.h"
#include "nibo/bot.h"
#include "nibo/leds.h"
#include "nibo/gfx.h"
#include "nibo/irco.h"
#include "nibo/motco.h"
#include "nibo/floor.h"
#define LINKS 0
#define VORNE_LINKS 1
#define VORNE 2
#define VORNE_RECHTS 3
#define RECHTS 4
#define SPEEDFACTOR 30
// Zustände
#define BLOCKIERT 1
#define AUSWEICHEN 2
#define FREI 0
#define HINDERNISLINKS 3
#define HINDERNISRECHTS 4
#define GERADEAUS 5
// Deklarationen von Hilfsfunktionen
void Init();
void float2string(float value, int decimal, char* valuestring);
void leds_set_status_all(uint8_t col0, uint8_t col1, uint8_t col2, uint8_t col3, uint8_t col4, uint8_t col5);
float SupplyVoltage(void);
void textout(int x, int y, char* str, int ft);
int main()
{
Init();
// Kollisionsvermeidung vorbereiten
uint16_t Vektor[5][2]; // Einheitsvektoren (*10) [0] ist x- und [1] ist y-Wert
Vektor[0][0] = -10; // LINKS x
Vektor[0][1] = 0; // LINKS y
Vektor[1][0] = -7; // VORNE_LINKS x
Vektor[1][1] = 7; // VORNE_LINKS y
Vektor[2][0] = 0; // VORNE x
Vektor[2][1] = 10; // VORNE y
Vektor[3][0] = 7; // VORNE_RECHTS x
Vektor[3][1] = 7; // VORNE_RECHTS y
Vektor[4][0] = 10; // RECHTS x
Vektor[4][1] = 0; // RECHTS y
uint8_t weightfactor[5]; // Gewichtungsfaktor
weightfactor[LINKS] = 1;
weightfactor[VORNE_LINKS] = 2;
weightfactor[VORNE] = 3;
weightfactor[VORNE_RECHTS] = 2;
weightfactor[RECHTS] = 1;
uint16_t VektorMalSensor[5][2]; // Sensorwert * Einheitsvektor (*10)
uint16_t VektorMalSensorSumme[2]; // Sensorschwerpunkt (x,y) für Auswertung
// Vorbereitungen
leds_set_displaylight(1000);
leds_set_headlights(256);
floor_enable_ir();
motco_setPWM(512,512);
motco_setSpeed(3,3);
// fixe Display-Anzeigen
textout(35,0,"Volt", 0);
textout(0, 8,"distance:", 0);
textout(0,24,"floor:", 0);
textout(0,40,"line:", 0);
// Hauptschleife
while(1)
{
// Akkuspannung anzeigen
float Ubatt = SupplyVoltage();
char text[6];
float2string(Ubatt,2,text);
textout(0,0," ",0); // 5 Zeichen löschen
textout(0,0,text, 0);
// Abstandsmessung Raumgefühl
irco_startMeasure();
irco_update();
// Floor
uint16_t floor_distance[2];
uint16_t line_distance[2];
// Abstandsmessung Floor
floor_update();
floor_distance[0] = floor_l;
floor_distance[1] = floor_r;
line_distance[0] = line_l;
line_distance[1] = line_r;
//Strings für Display
char irco_string[5][5];
char floor_string[2][5];
char line_string[2][5];
// Laufvariablen
int i,j;
/*
IR-Abstandssensoren
*/
for(i=0; i<5; ++i)
textout(i*21,16," ",0); //löschen
for(i=0; i<5; ++i) // z.Z. noch rechts 0 und links 4 !!!!!!!!!!!!!
{
itoa(irco_distance[i],irco_string[i],10);
textout(i*21,16,irco_string[i],0);
}
/*
IR-Floorsensoren (Abgrunderkennung)
*/
for(i=0; i<2; ++i)
textout(i*28,32," ",0); //löschen
for(i=0; i<2; ++i)
{
itoa(floor_distance[i],floor_string[i],10);
textout(i*28,32,floor_string[i],0);
}
/*
IR-Liniensensoren
*/
for(i=0; i<2; ++i)
textout(i*28,48," ",0); //löschen
for(i=0; i<2; ++i)
{
itoa(line_distance[i],line_string[i],10);
textout(i*28,48,line_string[i],0);
}
/*
MOTCO
Mathematische Methode "x/y-Schwerpunkt der Sensorvektoren bilden":
(Einheitsvektoren * 10) * Sensorwert (0-255) * weightfactor, davon Summe bilden
VektorMalSensorSumme[...] 0 ist x-Wert und 1 ist y-Wert
Blockade: y kann maximal 14790 groß werden (vl, v, vr 255)
Richtung: x kann maximal -6120 (Hindernis links) bzw. +6120 (H. rechts) werden (l, vl 255 bzw. r, vr 255)
*/
// Ermittlung von VektorMalSensorSumme[...] (gewichteter x- und y-Wert)
VektorMalSensorSumme[0] = 0; // x-Wert
VektorMalSensorSumme[1] = 0; // y-Wert
// i entspricht links, vornelinks, vorne, vornerechts, rechts
// j entspricht x und y
for (i=0; i<5; ++i)
{
for (j=0; j<2; ++j)
{
VektorMalSensor[i][j] = Vektor[i][j] * irco_distance[i] * weightfactor[i]; // 4-i wegen IRCo?????
VektorMalSensorSumme[j] += VektorMalSensor[i][j];
}
}
// Reaktion auf VektorMalSensorSumme[...] (x- und y-Wert)
// GrenzenY
uint16_t GrenzeY1 = 12000; // Zustandsgrenze: BLOCKIERT / AUSWEICHEN
uint16_t GrenzeY2 = 6000; // Zustandsgrenze: AUSWEICHEN / FREI
// GrenzenX
uint16_t GrenzeXlinks = -2000; // Zustandsgrenze: LINKS / GERADEAUS
uint16_t GrenzeXrechts = 2000; // Zustandsgrenze: RECHTS / GERADEAUS
// Zustandsvariable
uint8_t zustand = 0;
uint8_t zustand_old = 0;
// Zustand ermitteln
{ // y-Wert
if( VektorMalSensorSumme[1] >=GrenzeY1) zustand = BLOCKIERT;
if((VektorMalSensorSumme[1] < GrenzeY1) &&
(VektorMalSensorSumme[1] >=GrenzeY2))
{
// x-Werte
if( VektorMalSensorSumme[0] < GrenzeXlinks ) zustand = HINDERNISLINKS;
if( VektorMalSensorSumme[0] > GrenzeXrechts ) zustand = HINDERNISRECHTS;
if((VektorMalSensorSumme[0] >=GrenzeXlinks) &&
(VektorMalSensorSumme[0] <=GrenzeXrechts)) zustand = GERADEAUS;
}
if (VektorMalSensorSumme[1] < GrenzeY2) zustand = FREI;
}
// Auf Zustand reagieren
if(zustand == zustand_old)
{
// kein MOTCo-Befehl notwendig
}
else //Veränderung eingetreten
{
// Sondermaßnahmen
// gegen Schwingung links/rechts: einmal GERADEAUS erzwingen
if((zustand_old == HINDERNISLINKS) || (zustand_old == HINDERNISRECHTS))
{
zustand = GERADEAUS;
}
// gegen Schwingung vor/zurück: zweimal zurück
if((zustand_old == BLOCKIERT) && (zustand == GERADEAUS))
{
zustand = BLOCKIERT;
}
// direkt vorne frei?
if(irco_distance[2]<150)
{
zustand = zustand_old;
}
//Allgemeine Maßnahmen
switch(zustand)
{
case FREI:
//entry
leds_set_status_all(LEDS_OFF, LEDS_OFF, LEDS_GREEN, LEDS_GREEN, LEDS_OFF, LEDS_OFF);
//do
motco_setSpeed( 3*SPEEDFACTOR, 3*SPEEDFACTOR ); // rasch vorwärts
delay(10);
//exit
break;
case HINDERNISRECHTS:
//entry
leds_set_status_all(LEDS_OFF, LEDS_OFF, LEDS_OFF, LEDS_OFF, LEDS_ORANGE, LEDS_ORANGE);
//do
motco_setSpeed( -SPEEDFACTOR, SPEEDFACTOR ); // nach links drehen
delay(10);
//exit
break;
case GERADEAUS:
//entry
leds_set_status_all(LEDS_OFF, LEDS_OFF, LEDS_ORANGE, LEDS_ORANGE, LEDS_OFF, LEDS_OFF);
//do
motco_setSpeed( 2*SPEEDFACTOR, 2*SPEEDFACTOR ); // gemäßigt vorwärts
delay(10);
//exit
break;
case HINDERNISLINKS:
//entry
leds_set_status_all(LEDS_ORANGE, LEDS_ORANGE, LEDS_OFF, LEDS_OFF, LEDS_OFF, LEDS_OFF);
//do
motco_setSpeed( SPEEDFACTOR, -SPEEDFACTOR ); // nach rechts drehen
delay(10);
//exit
break;
case BLOCKIERT:
//entry
leds_set_status_all(LEDS_OFF, LEDS_OFF, LEDS_RED, LEDS_RED, LEDS_OFF, LEDS_OFF);
//do
motco_setSpeed(-2*SPEEDFACTOR,-2*SPEEDFACTOR ); // rückwärts fahren
delay(10);
//exit
break;
}
zustand_old = zustand;
motco_update();
}
}//Ende while-Hauptschleife
while(1);
return 0;
}
// Hilfsfunktionen
void Init()
{
sei(); // enable interrupts
i2c_init();
pwm_init();
display_init();
bot_init();
leds_init();
floor_init();
gfx_init();
}
void leds_set_status_all(uint8_t col0, uint8_t col1, uint8_t col2, uint8_t col3, uint8_t col4, uint8_t col5)
{
leds_set_status(col0,0);
leds_set_status(col1,1);
leds_set_status(col2,2);
leds_set_status(col3,3);
leds_set_status(col4,4);
leds_set_status(col5,5);
}
float SupplyVoltage(void)
{
bot_update();
return(0.0166 * bot_supply - 1.19);
}
void textout(int x, int y, char* str, int ft)
{
gfx_move(x,y);
gfx_print_text(str,ft);
}
void float2string(float value, int decimal, char* valuestring)
{
int neg = 0; char tempstr[20];
int i = 0; int j = 0; int c; long int val1, val2;
char* tempstring;
tempstring = valuestring;
if (value < 0){ neg = 1; value = -value; }
for (j=0; j < decimal; j++) {value = value * 10;}
val1 = (value * 2);
val2 = (val1 / 2) + (val1 % 2);
while (val2 !=0){
if ((decimal > 0) && (i == decimal)){
tempstr[i] = (char)(0x2E);
i++;
}
else{
c = (val2 % 10);
tempstr[i] = (char) (c + 0x30);
val2 = val2 / 10;
i++;
}
}
if (neg){
*tempstring = '-';
tempstring++;
}
i--;
for (;i > -1;i--){
*tempstring = tempstr[i];
tempstring++;
}
*tempstring = '\0';
}
Noch zum Thema Löten:
http://www.curiousinventor.com/guides/How_To_Solder
Eine der Probleme besteht oft darin, eine geeignete Fernbedienung mit RC5-Code sicher zu erwerben. Auf diesem Weg ist es mir beim Nibo gelungen: (Einstellung an Universalfernbedienung: TV1, 023)
https://www.roboternetz.de/phpBB2/vi...=303427#303427
Wo findet man eigentlich weiterführende Informationen über das Zusammenspiel der 3 Controller? Es gibt für den Nibo wohl eine Firmware, die über den ATMega128 die beiden ATtiny44 "flasht".
Es gibt im Wiki Infos über das .hex-File, aber keinen sourcecode. Warum werden Informationen über Bootloader und z.B. obige Firmware so ein Geheimnis gemacht? (Gilt auch für andere uC Hersteller).
Gruß
Lisbeth
Hallo Lisbeth! Ja genau so. Die Funktionsweise der Initializer-Software wird über die Jumper (vier Möglichkeiten) geregelt. Beim Nibo liegt alles "offen", manches allerdings unter der Motorhaube. Du kannst den gesamten Sourcecode einsehen:
https://nibo.svn.sourceforge.net/svn...ibo/trunk/src/
Am besten beschaffst Du Dir TortoiseSVN 1.4.4. http://tortoisesvn.net/
Damit kannst Du das Repository auf einfache Weise exportieren. Besorge Dir den Sourcecode immer von dort, nicht über Sourceforge, da dieses Paket nicht aktuell ist.
Verwendest Du MS Windows oder Linux als Betriebssystem?
Siehe z.B. ein kleines Hallo-Welt-Programm in C:
https://nibo.svn.sourceforge.net/svn...c/test1/test.c
Ich habe übrigens angefangen, Nibo in C++ zu programmieren. Nicht ganz einfach, aber es funktioniert prächtig. Hier ein kleines Beispiel:
Bin gerade an einer FSM nicht mit if/else oder switch/case, sondern gemäß http://www.ai-junkie.com/architectur...ut_state1.html mit Klassen, die den jeweiligen Zustand im Sinne eines "state design pattern" repräsentieren, falls Dich so etwas interessieren sollte.Code:#include <avr/interrupt.h>
#include "nibocc/niboconfig.hpp"
#include "nibocc/i2cmaster.hpp"
#include "nibocc/adc.hpp"
#include "nibocc/bot.hpp"
#include "nibocc/delay.hpp"
#include "nibocc/display.hpp"
#include "nibocc/floor.hpp"
#include "nibocc/graphicdisplay.hpp"
#include "nibocc/irco.hpp"
#include "nibocc/leds.hpp"
#include "nibocc/motco.hpp"
#include "nibocc/pwm.hpp"
#include "nibocc/textdisplay.hpp"
#include <stdlib.h> // RAND_MAX 32767
#include <stdint.h>
#include <string.h> // MyString
using namespace nibocc;
// Hilfsfunktionen
float SupplyVoltage(void);
// Hilfsklassen
/*****************
* Stringklasse *
******************/
// notwenig für WinAVR bis Mai 2007 bzw. bis GCC 4.1.2
// Ersatz für new, new[], delete und delete[] der fehlenden C++-Standard-Bibliothek
void* operator new (size_t size) { return malloc(size); }
void* operator new[] (size_t size) { return malloc(size); }
void operator delete (void* ptr) { free(ptr); }
void operator delete[] (void* ptr) { free(ptr); }
class MyString
{
private:
char * pData_;
public:
friend MyString operator+( const MyString &, const MyString & );
MyString() : pData_( NULL ) {} // inline ctor
MyString( const char * pText );
MyString( const MyString & text ); // Copy-Konstruktor
~MyString(); // dtor
const MyString & operator=( const MyString & text );
bool operator==( const MyString & text ) const;
char operator[]( int index ) const;
operator const char * () const; // cast zum C-String
operator char * () const; // cast zum C-String
int getLaenge() const;
void ausgeben() const;
};
MyString operator+( const MyString & leftstring, const MyString & rightstring );
/******************************************************************/
// ctor mit C-String als Argument
MyString::MyString( const char * pText ) : pData_( NULL )
{
if( pText )
{
pData_ = new char[ strlen( pText ) + 1 ];
strcpy( pData_, pText );
}
}
// copy-ctor
MyString::MyString( const MyString & text ) : pData_( NULL )
{
if( text.pData_ )
{
pData_ = new char[ strlen( text.pData_ ) + 1 ];
strcpy( pData_, text.pData_ );
}
}
// dtor
MyString::~MyString()
{
delete[] pData_;
}
// ==
bool MyString::operator==( const MyString & text ) const
{
if( pData_ == NULL || text.pData_ == NULL )
{
return ( pData_ == NULL && text.pData_ == NULL );
}
return ( strcmp( pData_, text.pData_ ) == 0 );
}
// []
char MyString::operator[]( int i ) const
{
if( i >= 0 && i < getLaenge() )
{
return pData_[i];
}
else
{
return '\0';
}
}
// Länge des Textes ermitteln
int MyString::getLaenge() const
{
if( pData_ == NULL )
{
return 0;
}
else
{
return strlen( pData_ );
}
}
// cast zu C-String
MyString::operator const char * () const
{
return pData_;
}
MyString::operator char * () const
{
return pData_;
}
// Zuweisungs-Operator
const MyString & MyString::operator=( const MyString & text )
{
if( this == &text ) // Selbstzuweisung abfangen
{
return *this;
}
delete[] pData_;
if( text.pData_ )
{
pData_ = new char[ strlen( text.pData_ ) + 1 ];
strcpy( pData_, text.pData_ );
}
else
{
pData_ = NULL;
}
return *this;
}
void MyString::ausgeben() const
{
// TODO
}
/******************************************************************/
MyString operator+( const MyString & leftstring, const MyString & rightstring )
{
MyString result;
if( leftstring.pData_ != NULL && rightstring.pData_ != NULL )
{
result.pData_ = new char[ strlen( leftstring.pData_ ) +
strlen( rightstring.pData_ ) + 1 ];
strcpy( result.pData_, leftstring.pData_ );
strcat( result.pData_, rightstring.pData_ );
}
else if( rightstring.pData_ != NULL )
{
result = rightstring;
}
else if( leftstring.pData_ != NULL )
{
result = leftstring;
}
return result;
}
class RandomStdlib // verwendet rand() aus <stdlib.h>
{
private:
const uint16_t seed_;
public:
RandomStdlib():seed_(static_cast<uint16_t>(3000*SupplyVoltage())){}
int getNum() const
{
static uint8_t seed_flag=0;
if(!seed_flag)
{
srand(seed_);
seed_flag = 1; // true
}
return rand();
}
};
template<typename T_Generator>
class Wuerfel
{
private:
const uint16_t maxzahl_;
const uint16_t maxrandom_;
T_Generator zahlengenerator_; // Template-Typ
public:
Wuerfel(uint16_t maxzahl):maxzahl_(maxzahl),maxrandom_(RAND_MAX-(RAND_MAX%maxzahl)) {}
uint16_t wuerfelt()
{
uint16_t r;
do{ r = zahlengenerator_.getNum(); }
while ( r >= maxrandom_ );
return ( r % maxzahl_ +1 );
}
};
int main()
{
sei();
Bot::init();
Leds::init();
Pwm::init();
Display::init();
Graficdisplay::init();
Leds::set_displaylight(1000);
Graficdisplay::move(0,10);
Graficdisplay::print_text("Nibo Lichtorgel", 0);
Graficdisplay::move(0,20);
Graficdisplay::print_text("mit Zufallsgenerator", 0);
Graficdisplay::move(0,40);
Graficdisplay::print_text("LED", 0);
Graficdisplay::move(40,40);
Graficdisplay::print_text("Color", 0);
MyString str, str1, str2;
str1 ="AVR-Programm mit";
str2 =" C++!";
str = str1 + str2;
Graficdisplay::move(0,54);
Graficdisplay::print_text( (char *) str, 0);
Wuerfel<RandomStdlib> w(6); // 1 ... 6
Wuerfel<RandomStdlib> c(3); // 1 ... 3
uint8_t wurf, color;
char text[2];
while(1)
{
static uint16_t pause = 1200;
pause -=50;
if(pause<50) pause = 50;
wurf = w.wuerfelt()-1;
color = c.wuerfelt();
itoa(wurf,text,10);
Graficdisplay::move(23,40);
Graficdisplay::print_text(text, 0);
itoa(color,text,10);
Graficdisplay::move(75,40);
Graficdisplay::print_text(text, 0);
Leds::set_status(color,wurf);
Leds::set_headlights(170*(wurf+1)); // 170...1020
Delay::delay(pause);
for(int i=0; i<6; ++i)
Leds::set_status(LEDS_OFF,i);
}
while(1);
return 0;
}
// Hilfsfunktionen
float SupplyVoltage(void)
{
bot_update();
return(0.0166 * bot_supply - 1.19);
}
@ehenkes:
1) Betriebssystem: Tut nix zur Sache! (Ich will keine Angriffsfläche für die diversen Fraktionen bieten :-) ) Der Nibo hat ja eh (noch) keins
2) C++: Welche Entwicklungsumgebung? Warum FiniteStateMachine?
3) Mein Vorschlag bzgl. Löten ist, dass es gut wäre, auch einen Fertigbausatz (vielleicht ohne mechanische Montage) gegen Aufpreis anzubieten. Der RP6 kostet ja fertig 129 EUR und das bei "nur" einen ATMega32.
4) Kann man hier im roboternetz eventuell die Technischen Daten der 3 hier so heiß diskutierten Roboter Asuro, Nibo und RP6 im Vergleich reinstellen?
5) Wie ich anderswo schon schrieb, liebe ich meine rasende Leiterplatte Asuro (mit Hüftschaden), weil er so ist, wie er ist. Zum Nibo muss ich erst noch ein Verhältnis aufbauen, aber er kommt mir jetzt schon ein wenig altklug vor....
6) So, und jetzt hör ich für heute auf: Nibo blinkt und rotiert.
Bis demnächst
Lisbeth
@Lisbeth:
ad 1) Mutig! Zu Nibo OS: Da gibt es FreeRTOS: http://www.cypax.net/snippets/index?...=de#mu-tasking
ad 2) Ich verwende AVR Studio + WinAVR für C++, habe nix Besseres. FiniteStateMachine (FSM) für ein Bewegungs-/Antikollisions-Programm
ad 3) Fertig bestückte Platine? Da gibt es doch dieses Problem mit dem 7805, der erst zum Schluss nach dem Anziehen der Schrauben festgelötet wird. Wartet man eine gewisse Zeit, kann man Nibo sicher fertig zusammen gebaut via ebay ergattern. Ich nehme Deinen kaum gebrauchten Nibo sofort, wenn Du "Traktoren" nicht magst. Da könnte ich die Kommunikation via RC5-Code testen. ;)
ad 4) vielleicht noch den c't-Bot dazu nehmen. Der Entwickler hat den Nibo basierend auf den Erfahrungen mit ASURO und c't-Bot entwickelt. Technische Daten sind aber noch nicht alles. Nibo's Vorteil sind die 5 IR-Sensoren. Die vorhandenen Dokumentationen, Programme, Bibliotheken und Erfahrungen sind ebenfalls wichtig.
ad 5) "rasende Leiterplatte" "altklug" - nicht übel! Weiter so. :)
ad 6) Die berühmte "Initializer.hex", deren Sourcecode Du ja nun auch kennst. Ich verwende übrigens noch eine Version vom 18.07., weil bei den neuen Versionen irgendwie Odometriedaten verloren gehen und Nibo suizid-gefährdet durch die Gegend schießt. Da ist der ASURO eine lahme Seifenkiste dagegen.
Tipp: Lege Dir mindestens zwei Akku-Sätze bereit. Nibo ist ein Energiebündel, kein Leisetreter.
Bin auf Deine Ideen, Vorschläge und Programme gespannt! Hoffentlich machst Du bei C++ mit. "ASURO ist C, Nibo ist C, C++ und Java." 8-[
Noch eine Frage: Du bist doch an MS Robotics Studio interessiert? Wie stellst Du Dir die Implementierung für den Nibo vor?
Wa sind deine Hauptinteressen bezüglich Programmierung des Nibo?
So, da bin ich wieder!
1) Mal eine Frage, den Verbrauch betreffend: soweit ich weiß, haben Asuro und Nibo die gleichen Antriebsmotoren. Diese sind doch die größten Verbraucher, oder? (Mein Nibo hat kein Display!) Wieso braucht Nibo so viel mehr Leistung?
2) Gibt es ein "HowTo" zum Laden des ersten selbsterstellten Programms? In etwa so: Starten Atmel Studio 4.13, Einbinden der header .... (Pfadangaben ...), Kompilieren, Flashen (per ISP-Schnittstelle)
3) 7805: Eine fertig bestückte Leiterplatte kann leicht verwendet werden (ohne "nachlöten"). Ich würde übrigens niemals meinen Asuro und Nibo bei ebay verhökern!! Was sind das für Menschen....
4) MSRS: anderer Faden, aber ich verstehe dort die Aussage: ... service fertig nicht?!?!
Gruß
Lisbeth
1) http://nibo.editthis.info/wiki/Stromversorgung (Verbrauchsdaten)
Das Display ist doch das Sahnehäubchen beim Nibo! Ohne Display könnte ich mir überhaupt nicht vorstellen.
2) Ist in Entwicklung. Frage mal beim Entwickler nach. Vielleicht erhälst Du eine Vorabversion. Wenn nein, sagst Du mir Bescheid, dann stelle ich ein kleines Beispiel für AVR Studio auf meine Homepage. Wenn Du das allerdings noch nicht alleine schaffst, wird C++ schwierig, da man da alles manuell im makefile erledigen muss. AVR Studio unterstützt C++ nicht wirklich, es duldet es nur. Das Thema muss ich wohl auf meiner Homepage beschreiben, wenn das Programmiertutorial das nicht umfasst.
3) Du hängst also doch schon etwas an dem "altklugen" Traktor. ;)
4) "... service fertig nicht?!?!" Wie meinen? :)