Liebe Community,
ich bin auf eure Hilfe angewiesen.
Ich versuche schon seit mehreren Monaten den OV7670 (VGA-Modul) mit dem
mit einem Atmega 328P anzusteuern.
Dabei scheitere ich allerdings schon bei der ansteuerung bzw. der
Kommunikation mit dem SCCB-Interface zur Steuerung des Moduls.
Nach studium diverser Datenblätter und Websiten dachte ich, die
Funktionsweise verstanden zu haben und das Problem läge in einer
fehlerhaften ungewollten Programmierung. Nachdem ich nun aber auch
endlich stolzer Besitzer eines Oszilloskops geworden bin, muss ich
feststellen, dass alle Pins so schalten, wie ich es mir vorstelle und
dass ich offensichtlich nicht verstehe, was zu tun ist. Daher wende ich
mich an euch und hoffe auf einen Hilfsbereiten der sich erbarmt meine
Wissenslücke zu füllen.
Um die Funktionsweise des SCCB sicherzustellen sieht mein Plan vor,
ersteinmal nur das Register 0x01 auszulesen und den Default-Wert 0x80
als Antwort zu bekommen. Um das zu erzielen sieht mein Plan folgendes
vor:
2-Phasen Write Zyklus gefolgt von einem 2-Phasen Read Zyklus.
Dazu sende ich folgende Befehle:
0x42 + 0 + 0x01 + 0 + 0x43 + 0 + Eingang + 1
(die Nullen bzw. 1 stellen hier die mitgeschickten Don't care Bits dar)
Nach meinem bisherigen verständnis sollte doch während der letzten Phase
(hier mit Eingang bezeichne) die Daten vom Slave, also dem Kamaramodul
aus geschrieben werden. Ich erhalte allerdings nur ein durchgehendes
HIGH oder LOW jenachdem, ob ich die SIOD Leitung mit dem Pull-Up an 3,3V
hänge.
Abweichend zu dem Anschlussplan, betreibe ich die xCLK über einen
Arduino Nano mit einer Frequenz von 16kHz.
Gerne führe ich mein Problem weiter aus, hoffe aber schoneinmal, dass
sich jemand dazu berufen fühlt mir zu helfen.
vielen Dank!
lg.
David
Moin,
ich kenne das Modul nicht, aber wenn ich mir das ansehe:
https://github.com/maslovk/STM32_OV7670/blob/master/Src/OV7670.c
wird die Reset Leitung auf L gelegt, dann 100ms gewartet, dann auf H.
Danach wird an I2C 8bit Adresse 0x42 ein 0x0A gesendet und es kommt ein
0x76 zurück.
Bitte entschuldigt die verzögerte Antwort. Leider war ich die Woche
beruflich sehr eingespannt, weshalb ich nicht dazu gekommen bin, weiter
zu basteln und zu versuchen.
Zur Aussage von Pegel, das ist richtig. Da dieser Baustein in Verbindung
mit diversen Arduino sets angeboten wird, bin ich davon ausgegangen,
dass ich ihn direkt an dem Uno betreiben kann.
Sollte ich etwa jeden Pin noch über einen Spannungsteiler reduzieren?
Es kommt etwas drauf an welches Modul Du gekauft hast. Der Chip selbst
(OV0706) hat eine Betriebsspannung um 3,3V. Das häufig erhältliche
OV7670 Modul mit Linse wird oft mit 5V TTL Interface, direkt für Arduino
angeboten. Das ist dann ein Pegelwandler enthalten.
Hab grad nochmal im Datenblatt nachgeschaut. Also die Vio ist dort mit
1.7 - 3.0V angegeben. Berichten zufolgen sollen 3.3V jedoch
"unbedenklich" sein.
Du brauchst also höchstwahrscheinlich einen Pegelwandler für jedes
Signal zwischen Arduino und Kamera.
David D. schrieb:> Ich versuche schon seit mehreren Monaten den OV7670 (VGA-Modul) mit dem> mit einem Atmega 328P anzusteuern.
Offensichtlich verfolgst Du einen eher akademischen Ansatz, sprich Du
bist nicht auf eine schnelle Lösung ohne Hintergrundinformation aus. Das
ist schön, denn dann kann man sich alle Links auf die div. Umsetzungen
sparen. Damit lernt man nämich nix, wenn man das fertige Gedankengut
eines anderen einfach verwendet.
> Dabei scheitere ich allerdings schon bei der ansteuerung bzw. der> Kommunikation mit dem SCCB-Interface zur Steuerung des Moduls.
Deine Vorgehensweise ist auf jeden Fall richtig. Erstmal nur das
Kommandointerface zum laufen zu bringen und den Rest aussen vor zu
lassen. Solange man keinen PCLK anlegt, gibt der Chip ohnehin keine
Videosignale aus.
Die Kommunikation mit dem SCCB-Teil läuft über den 2-Wire Bus ab. Ob und
in wie weit der zu 100% der SPI-Spezifikation entspricht konnte ich
leider nicht ermitteln. Von daher wäre es, für den Anfang ein guter Plan
nicht die fertigen I2C-Libs zu nutzen, sondern die Signale via
"Bitbangig" selbst zu generieren.
Zum Glück arbeitet der 2-Draht-Bus statisch, man kann sich also ruhig
Zeit lassen. Es gibt keine minimale Taktfrequenz, nur max. 400 kHz.
Dein Setup mittels Arduino ist vollkommen ok, nur einen Pegelwander für
die beiden Signale solltest Du zwingend vorsehen. Ein Spannungsteiler
wäre für die SIO_C (CLK) noch ok, aber für die SIO_D sollte es schon ein
richtiger Pegelwandler sein. Im einfachsten Fall mit Transistoren (gibts
hier auf der Website auch als Schaltbeispiel) oder halt ein
entsprechendes IC. Später, bei den Videosignalen, braucht man das auch.
Für die SCCB-Kommunikation würde anfangs sowas hier reichen:
https://www.roboter-bausatz.de/434/i2c-pegelwandler/level-konverter-3.3v-5v-bidirektional-2-kanal
Steht die Hardware, können wir uns der Kommunikation widmen. Dafür sind
vor allem die START- und STOP-Konditionen wichtig.
Ohja, was noch wichtig sein dürfte. Betriebsspannung anlegen, 3.3V ;-),
PWDN auf GND (ist Active High), RESET auf 3.3V (active low).
Und dann ist da noch der Systemtakt, XCLK. Laut Datenblatt sind hier
wenigstens 10 MHz anzulegen. Vermutlich damit die interne Logik
überhaupt arbeitet und damit auch das I2C Interface.
Diesen Takt kann man z.b. vom Arduino mittels PWM erzeugen lassen.
Selbstredent muss hier auf der richtige Pegel verwendet werden, also
besser gleich einen 4fach Pegelwandler nehmen.
Bei mir ist es schon wieder eine Weile her, als ich mal einen
Omnivision-Sensor über den SCCB angesteuert hab.
Aber ist das bei SCCB nicht so, das du zum Lesen eines Registers erstmal
einen Schreibbefehl senden mußt, um dann bei der nächsten
Datenübertragung den Registerwert zurückzubekommen?
Genau so ist es. Es ist übrigens schon möglich die Arduino I2C-Lib
("Wire.h") für die Kommunikation zu nutzen. Es kommt jetzt etwas drauf
an wie tief der Thread-Ersteller hier einsteigen möchte. Habs grad mal
auf die Schnelle mit einem Testaufbau nachgestellt. Klappt.
Für das grundsätzliche Verständnis wäre die eigene Implementation schon
gut. Will man sich aber "nur" mit der Kamera beschäftigen ist es nicht
zwingend notwendig.
David hat sich bislang nicht mehr gerührt, aber ich fang einfach mal so
an :-)
Eigentlich bietet fast jeder noch so kleine uC bereits ein I2C-Interface
On-Board. Auch hat mein kleiner Test gezeigt, das der Arduino darüber
problemlos mit dem OV7670-Modul kommunizieren kann. Daher sehe ich nicht
viel Sinn darin die I2C-Kommunikation per Bit-Banging zu emulieren.
Einzig David "besteht" darauf...
Wichtig dafür das es auch funktioniert ist eine vernünftige Verbindung
beider über einen Pegelwandler. Ohne halte ich das Unterfangen für mehr
als fraglich. Das von David gepostete Pinout kann m.E. nicht
funktionieren, da einfach alle Signale (3.0V IO-Pegel vom OV7670 und
5.0V Pegel vom Arduino) verbunden sind. Habe mal auf die Schnelle einen
Eagle Schaltplan gezeichnet, wie ich es aktuell aufgebaut habe. Als
Pegelwandler kommt fast alles in Frage, hauptsache Bidirektional
(wichtig für I2C!).
Den Systemtakt XCLK erzeuge ich über Manipulation der Timer-Register:
1
pinMode(9,OUTPUT);
2
TCCR1A=((1<<COM1A0));
3
TCCR1B=((1<<WGM12)|(1<<CS10));
4
TIMSK1=0;
5
OCR1A=0;
Hiermit erhalte ich an Pin 9 einen Takt von 8 MHz. mit 50% Duty-Cycle.
Laut Datenblatt müssten es mind. 10 sein. Leider kann der Uno nicht mehr
liefern mit seinen 16 MHz Systemtakt. Aber es scheint auch so zu
funktionieren.
Damit wäre das Setup bereit für die Programmierung des Chips ansich.
Hallo zusammen,
das Thema interessiert mich immer noch brennend und ich bin dankbar für
eure ausführlichen Beschreibungen.
Das mit dem Pegelwandler scheint für mich ein sehr unterschätzter Punkt
zu sein, den ich als erstes betrachten und korrigieren werde.
den xCLK betreibe ich über einen zweiten Controller (Arduino Nano) an
dem ich einfach die CKOUT-Fuse gesetzt und bekomme damit erstmal meine
16 Mhz über den PB0 Pin geliefert. (allerdings wieder ohne
Pegelwandlung... ja ich gestehe mir ein, ich muss den vorgegeben
Spannungen definitiv mehr Aufmerksamkeit schenken)
ab Mittwoch wird es bei mir hoffentlich etwas ruhiger (stehe grade
mitten in meiner Masterthesis Erstellung und der Bewerbungsphase für den
Berufseinstieg) sodass ich mich spätestenz zum Wochenende endlich
nochmal dem uController zuwenden kann.
den I2C benutze ich zur Zeit nicht, weil ich irgendwo gelesen hatte,
dass das SCCB nicht ganz dem Protokoll entspricht. Lasse mich da aber
sehr gerne belehren wenn das damit einfacher geht :)
Stelle auch gerne meinen Code zur Einsicht/Fehleridentifikation zur
Verfügung, wobei ich grade eher die Hoffnung habe, dass der Fehler in
der Spannungsversorgung ist.
Werde zum Wochenende hin auch hoffentlich einmal meinen ganzen
Anschlussplan erstellen und mit euch teilen.
@Olli "Offensichtlich verfolgst Du einen eher akademischen Ansatz.."
Ob ich da jetzt wirklich wissenschaftlich an die Sache ran gehe wage ich
noch etwas zu bezweifeln :D aber ja ich will es verstehen und nicht nur
irgendwelchen Code Copy'n'Pasten.
Das mit dem Pegelwandler würde ich mir ersparen. Wenn du den AVR mit 8
Mhz betreibst, reichen für diesen auch 3Volt. Für eine gescheite
Auflösung ist der avr eh zu langsam. Ein stm32f407-board mit
dcmi-camera-Schnittstelle kostet um die 10€. Auch damit ist der Betrieb
des camera-Moduls noch anspruchsvoll genug.
Was die Auflösung und Frame Rate angeht hab ich mir auch schon gedacht,
dass er dafür zu langsam ist. Mir reicht es aber in erster Linie auch
erstmal einfach nur ein Bild von einem statischen Motiv zu machen.
Ich würde auch gerne bei einem AVR bleiben, weil ich nur damit
Erfahrungen habe.
Mit ein paar kleinen Enschränkungen sollte das auch mit dem Uno
funktionieren. Es gibt zwei Versionen der 0.3 MP Kamera OV7670, eine
ohne und eine mit zusätzlichem FIFO-Bildspeicher.
Bei der Version ohne FIFO muss man die Bilddaten in der nativen
Geschwindigkeit des Sensors erfassen können. Ist die MCU zu langsam,
verliert man Daten und das ganze Bild ist unbrauchbar. Bei der Version
MIT FIFO Speicher werden die Bilddaten eines Frames in diesen abgelegt
und man hat "alle Zeit der Welt" sich die Daten abzuholen. Natürlich
verliert man dabei Frames, aber jedes ist konsistent.
Ich habe beide Versionen der Kamera hier. Man muss auch sagen das der
OV7670 die unterste Einsteigsklasse der Kameras ist. Wenn wir mit dem
Modell ohne FIFO arbeiten und die Daten nicht in Echtzeit in den Arduino
laden können, dann müssen wir einfach die Auflösung und Bildrate
reduzieren bis es klappt. Es geht hier ja erstmal auch nur um einen
"Proof-of-Concept", nicht wahr :-)
Neben der Hardware sollten wir auch die Software diskutieren, denn die
ist ja nicht weniger wichtig. Um dem ganzen eine gewisse Nachhaltigkeit
zu geben, habe ich hier in meinem Wiki mal einen Bereich dafür angelegt:
http://e-wiki.denkdose.de/video/ccd-sensor/ov7670/start
Dort würde ich alle Eregebnisse zusammentragen.
Zur Takterzeugung:
Laut Datenblatt des OV7670 sollten es mind. 10 MHz sein. Wie gesagt hat
es bei mir mit 8 MHz, welche sich ohne Tricks einfach per
umprogrammierung eines PWM-Timers erzeugen lassen geklappt.
Durch ändern der FUSE-Bits kann man den, beim Arduino Uno/Nano durch
einen externen 16 MHz Quarz erzeugten Takt auf dem PORTB Bit 0 (PB0) 1:1
durchreichen. PB0 liegt beim Uno/Nano auf dem Port "D8". Um das zu tun
sind jedoch einige tiefergreifende Modifikationen der IDE (boards.txt)
notwendig, da die FUSEs sich nicht innerhalb der Software anpassen
lassen, sondern zum Zeitpunkt der Chip-Programmierung eingestellt
werden.
Ich schlage daher vor, den o.g. Code zu nutzen und erstmal darauf zu
vertrauen das 8 MHz ausreichend sind. Im Prinzip könnte man auch den
Quarz umlöten auf 20 MHz. Das hält der 328p locker aus. Aber auch das
würde ich erst in Erwägung ziehen, wenn es zwingend sein muss.
Zur Pegelanpassung:
Das Taktsignal "XCLK" für den Kamerachip, sowie die SIO_C und SIO_D
Leitung sollten zwingend über einen Pegelwandler betrieben werden. Das
ist für mich alternativlos, auch wenn es Beschaltungen und Berichte gibt
die ohne auskommen. Diese nutzen den Umstand das die IO-Pins mit
Schutzdioden versehen sind, manche sind wenigstens so gändig und
schalten Widerstände in Reihe. Im von Dir gezeigten Schaltbild wird man
per Software wohl die Ausgänge ohne internen Pullup beschalten, also
quasi Open-Collector. Den High-Pegel erzeugen dann Pullups auf 3.3V. Das
könnte durchaus klappen, funktioniert aber bei der Clockerzeugung so
nicht. Dafür hat man da wohl den Serienwiderstand eingebaut, quasi
Pegelwandler für Arme ;-)
Kann man alles mal ausprobieren... was ich noch nicht untersucht habe
ist, ob sich durch den Pegelwandler die Flankensteiheilt irgendwie
problematisch verändert. Bislang gehe ich davon aus das der von mir
verwendete, auf Transistoren basierende, da keinerlei Probleme
verursacht.
Was die Datensignale angeht, könnte man durchaus auf einen Wandler
verzichten, da man diese ja nur liest. Der TTL-Pegel ist hier
abwärtskompatibel mit dem 3.0V Pegel des Kamerachips.
Auch wenn geht, würde ich hier ebenfalls auf Modifikationen des Uno, wie
andere Betriebsspannung, etc. verzichten. Wenn man an einer ernsthaften
Anwendung interessiert ist, sollte man einfach auch die passenden Chips
dafür wählen und da ist der STM32 (Bluepill) einfach besser geeignet
(stärker, billiger, richtiger Pegel, eigenes Interface, etc.).
Neben den Bilddaten-Pins D0-D7 benötigen wir auch den PCLK, VSYNC und
HREF um die Daten synchron einlesen zu können. VSYNC gibt uns den Start
eines Frames, HREF den einer jeden Zeile. PCLK zeigt uns wann welche
Pegel (auch die der Datenbits) stabil anliegen.
Zur Software:
Wenn Dein Hardwareaufbau steht, würde ich als erstes die grundlegende
Kommunikation (Protokoll) zwischen Arduino und OV7670 besprechen. Dies
soll es uns am Ende ermöglichen die Register des Chips zu lesen und zu
schreiben, sowie die für uns relevanten herauszufinden, sodass wir dem
Chip die passenden Einstellungen geben können.
Wenn das klappt, machen wir uns Gedanken wie wir einen Frame lesen und
daraus eine Bilddatei für den PC produzieren. Etappenziel wäre es, ein
Einzelbild in S/W zu übertragen und darzustellen. Danach können wir uns
allen weiteren Themen wie der Farbtransformationsmatrix (YUV<->RGB) etc.
widmen.
Was mich persönlich noch interessiert wären die OSD-Funktionen des
Chips. Laut Datenblatt soll man Zeichen und eine Overlaygrafik
darstellen können. Das wäre schon interessant. Auch kann man Bereiche
definieren in denen die Kamera auf Änderungen "reagiert" (Überwachung).
Ganz pfiffige haben Software zur Kanten- und Objekterkennung
(Verfolgungsmodus) geschrieben. So weit werden wir es sicher nicht
bringen...
Was aber noch denkbar ist, ist der Anschluß eines LCD-Panels um das Bild
gleich 1:1 anzuzeigen. Mit dem Uno/Nano wird das aber langsam knapp,
sowohl an MCU-Ressourcen als auch an Pins.
Die grundlegende Kommunikation auf dem SCCB entspricht der von I2C. Der
Busaufbau ebenfalls. Die Kamera agiert dabei als Slave und der Arduino
muss folglich den Master machen. Das heisst sowohl beim schreiben, als
auch beim lesen von Daten geht das immer vom Master aus.
Ein Slave reagiert nur auf eine bestimmte Adresse, welche im Fall des
Ov7676 scheinbar die 0x21 ist, auch wenn ich das im Datenblatt nirgens
finde.
Eine Bit-Übertragung beginnt immer mit einer Start-Kondition bei der die
SDA Leitung nach Low geht während SDC noch High ist. Der Empfänger
stellt sich aufs lesen von Daten ein. Es folgt eine Übertragung von 8
Bit langen Datenwörten, wiederum gefolgt von einer Stop-Kondition. Dabei
geht der Pegel von SDA auf High während SDC bereits High-Pegel hat. Nur
zur Info, normalerweise muss während der High-Phase von SDC der Zustand
von SDA stabil sein.
Konzentrieren wir uns nun auf die Nutzdaten des Protokolls. Hier sendet
der Master zuerst die Adresse des anzusprechenden Slave. Ab hier gibt es
nun ein paar Varianten, abhängig davon was man tun will.
Im „3-Phase-Write Cycle“ wird nach der Empfänger-ID die Subadresse, im
Fall des OV7676 ist es das zu beschreibende Register (COM...),
übertragen. Ihr folgt der Wert welcher in das Register zu schreiben ist.
Im „2-Phase-Write Cycle“ werden nur Empfänger und Subadresse
geschrieben. Diese Variante ist zur Vorbereitung der dritten
Übertragungsart, dem Lesezyklus gedacht. Sie selektiert das zu lesende
Register im Slave.
Beim „2-Phase-Read Cycle“ muss ein 3- oder 2-Phase-Write vorausgegangen
sein. Nach dem senden der Slaveadresse wird der Master passiv und
erwartet das der Slave nun seine Daten sendet.
Um also Daten aus dem Chip zu lesen, müssen vorher welche geschrieben
werden. Dies resultiert aus dem Umstand das ein Slave nicht
selbstständig auf den Bus senden darf.
Das Arduino Framework verwendet hierfür die „Wire“ Library.
Soviel erstmal zum Protokoll. Natürlich habe ich jetzt Komplexität
wissentlich unterschlagen, wie NA und ACK Bits, Multi-Master Busse, etc.
Guten Abend,
ja genauso hatte ich das Protokoll des SCCB auch verstanden.
Wenn du dir nochmal den Anhang in meinem Eröffnungspost anschaust,
sollten auch die vier Zyklen erkennbar sein. Wenn man dort die einzelnen
Bits anschaut (nach meinem Verständnis) wurden dort auch die richtigen
Adressen gesendet. Nur das was eben vom Slave nachher zurückkommt - in
dem letzten Zyklus - ist eben nur ein high Pegel mit falschem
Informationsgehalt.
Nach euren Ratschlägen habe ich mir eine weiteren OV7670 diesmal mit
AL422B Fifo und ein paar LVL-Shifter gekauft. Die sind heute angekommen.
Ich habe mich dann heute auch mal an Eagle gesetzt. Nunja um es kurz zu
machen bin ich da noch nicht so ganz routiniert ;-) sondern eher
komplett Neueinsteiger (ich arbeite noch an der Darstellung und der zum
Teil unvorteilhaften Beschriftung).
Der neue OV7670 weist schon mal mehr PINs auf, was vermutlich auf das
FIFO zurückzuführen ist. Hier tun sich für mich jetzt in erster
Betrachtung zwei Fragen auf:
1. Wenn das Bild im FIFO abgelegt wird, wozu werden dann noch VSync und
HREF nach außen geführt? Eventuell zum Zählen um festzustellen ob das
Bild fertig vorliegt?
2. xCLK ist nicht mehr vorhanden. Womit gebe ich dann den Takt vor?
eventuell befindet sich auch der Quarz schon auf der Kamera Platine?
Ich konnte mich leider noch nicht detaillierter mit der Sache
auseinander setzten und in den Datenblättern oder dem Internet großartig
stöbern, wollte euch aber an meinen Gedankengängen teilnehmen lassen.
lg.
David
PS: Übrigens arbeite ich nicht mit der Arduino Umgebung, sondern direkt
mit dem Atmelstudio auf der Atmelbasis. Sind die genannten Bibliotheken
sehr komplex? oder kann man sich das ganze auch selber
zusammenschreiben, bzw. ummünzen?
Hallo David. Ich würde nicht mitten drin die Verhältnisse ändern. Du
schaffst gerade neue Probleme. Lass uns doch erstmal mit der "alten"
Kamera ohne FIFO weiterarbeiten. Das Bild interessiert uns doch aktuell
noch nicht. Dabei ist es völlig egal ob das Teil nene Fifo hat oder
nicht und wie und ob die Sync-Signale genutzt werden.
Hier ein Test-Code
Hallo,
es kann vielleicht trotzdem helfen bei Arduino vorbeizuschauen.
https://github.com/ComputerNerd/ov7670-no-ram-arduino-uno
Ich habe mit der OV7670 ohne FiFo nur kurz rumgespielt, allerdings an
einem ESP32. Eigentlich ist die OV7660 eine komplette Enttäuschung für
mich.
Dann habe meine uralten DC3840 und MCA-25 rausgekramt...
Die DC3840 lief ja vor Jahren schließlich mal stabil bei mir an einem
AVR-NetIO mit einem Mega32.
http://www.ulrichradig.de/home/index.php/projekte/uC-kamera
Allerdings sind diese Cams wohl inzwischen kaum noch aufzutreiben.
Gruß aus Berlin
Michael
Danke für den Link zu der OV-Software, das wird später hilfreich sein!
David und ich wollen aber erstmal bei dem ursprünglich genannten Modell
bleiben um uns nicht zu verzetteln. Das wäre erstmal ans Laufen zu
bringen und dann können wir das Gebiet erweitern :-)
Eine Frage zu den I2C-Leitungen vom Arduino. Laut I2C Spezifikation
müssen die Pins für SDA und SCL open drain mit einem 2,2 k Pullup
bestückt sein.
Auf dem Schaltplan vom Uno kann ich keinerlei externe Pullups finden.
Im Quellcode der Wire-Library (twi.c) ist für Wire.Begin():
// activate internal pullups for twi.
digitalWrite(SDA, 1);
digitalWrite(SCL, 1);
und Wire.end() dieses enthalten:
// deactivate internal pullups for twi.
digitalWrite(SDA, 0);
digitalWrite(SCL, 0);
Vorausgesetzt beide Ports sind als Eingänge definiert (DDR-Register),
aktiviert bzw. deaktiviert dies in der Tat die internen Pullups und hat
die gleiche Wirkung wie z.B.:
pinMode(SDA, INPUT_PULLUP);
pinMode(SCL, INPUT_PULLUP);
Sowohl SCL (wenn der Arduino als Slave arbeiten würde) als auch SDA
können zeitweise auch als Ausgänge konfiguriert sein.
Im Datenblatt vom Atmega328p finde ich hierzu:
SCL/ADC5/PCINT13 – Port C, Bit 5
– SCL: 2-wire Serial Interface Clock. When the TWEN bit in TWCR is set
(one) to enable the 2-wire Serial Interface, pin PC5 is disconnected
from the port and becomes the Serial Clock I/O pin for the 2-wire Serial
Interface. In this mode, there is a spike filter on the pin to suppress
spikes shorter than 50 ns on the input signal, and the pin is driven by
an open drain driver with slew-rate limitation.
SDA/ADC4/PCINT12 – Port C, Bit 4
– SDA: 2-wire Serial Interface Data. ... <der gleiche Text wie SCL>
Wenn ich das alles richtig im Quellcode vom Arduino verstehe, dann wird
bei Wire.begin() das TWEN-Bit in TWCR gesetzt und beim Wire.end() wieder
gelöscht. Im I2C-Modus sind beide Pins wirklich auch open-drain und
benötigen einen Pullup. Sobald man den I2C-Modus aber wieder verlässt,
liegen die IO-Pins wieder an.
Ich muss das manl nachmessen...
Hallo,
aua, da müßte ich jetzt auch stark das Datenblatt des Mega328
befragen...
Meiner Erinnerung nach bleibt die PullUp-Funktion auch dann aktiv wenn
TWEN gesetzt wird. Es wird nur die OUT-Stufe umgeschaltet, die PullUp
müßten zur IN-Hardware gehören und damit weiterhin ein-/ausschaltbar
sein. IN bleibt ja mit dem Pin verbunden.
Gruß aus Berlin
Michael
In dem Fall wäre aber das häufig zu findende, im erster Post abgebildete
Pinout mit den beiden externen Pullups zu 3,3V falsch. Das würde ja,
alternativ zu einem Pegelwanlder, nur funktionieren wenn die Ausgänge
wirklich ausschließlich opendrain wären.
Zum Einschaltzeitung (Resetphase) sollen die Pins laut Datenblatt
Tristate sein. Soblad ich Zeit hab prüfe ich das mit einem Uno/Nano und
dem DSO mal nach...
Hallo,
nach Rest sind sie triState und der interne PullUp ist aus.
Setze ich den Pin über DDR auf Ausgang ist die Push-Pull-Stufe aktiv.
Schalte ich TWEN aktiv ist die Ausgangsstufe openDrain, meiner
Erinnerung nach völlig unabhängig vom Zustand des DDR-Bits (da müßte ich
jetzt aber ins Datenblatt schauen).
Die exiernen PullUp sind für I2C nötig wegen der OpenDrain Ausgänge.
Wenn jetzt mit dem Portbit der interne Pullup eingeschaltet wird liegen
eben diese ca. 50k parallel zum externen PullUp, stört doch keinen.
Wenn keine externen pullUp da sind und der interne eingeschaltet wird,
hat der I2C eben diese 50k als PullUp. Das funktioniert in der Praxis
auch dzurchaus bei nur einem Slave am Bus und kurzen Leitungen und z.B.
100kHz I2C-Clock. Ist aber natürlich nicht normgerecht.
Praktisch kommt bei den China-BreakOut-Board noch dazu, daß jeder macht
was er will. Mal sind auf den Modulen PullUps an SDA/SCL, mal
Pegelwandler, mal garnichts...
Gruß aus berlin
Michael
Mir ging es nicht um die Pullups selbst, sondern vielmehr um die
Spannungspegel. Wenn ich auf einem Uno Board zu irgendeinem Zeitpunkt
die internen Pullups aktiviere, oder wenn die Ausgangsstufe im Push
Modus einen High Pegel erzeugtm dann habe ich doch 5V am jeweiligen
Signal. Da nutzt dann der externe Pullup gegen 3,3V doch auch nichts
mehr...?,
Hallo zusammen, ich melde mich nach einigen versuchs Stunden.
@Olli
Ich gebe dir recht, dass wir die Startbedingungen nicht ändern sollten
und bin deswegen wieder auf die Kamera ohne Fifo umgestiegen.
Da ich bislang, wie schon erwähnt, nicht mit der Arduino IDE gearbeitet
habe, sondern mit dem Atmel Studio, stellen sich für mich die ganzen
Sachen etwas komplexer dar. Um aber die Fehler eingrenzen zu können, hab
ich mich jetzt einmal dazu durchgerungen zumindest testweise auf die
Arduino IDE umzusteigen. Ich habe es allerdings nicht geschafft, die
bisher genutzten Controller über diese anzusteuern. Vermutlich habe ich
den Bootloader beim ISP Programmieren überschrieben.
Glücklicherweise habe ich noch einen unbenutzten Nano gefunden, mit dem
ich das ganze zum laufen gebracht habe. Ich denke, ob ich jetzt zur
Ansteuerung am Anfang den Nano oder den Uno verwende, sollte keinen
Unterschied machen. (Bitte belehrt mich wenn ich falsch liege)
zu deinem geposteten Test-Code:
Über das I2C Interface wird das ganze definitiv viel Übersichtlicher als
in meinem bisherigen Programmcode, in dem Ich die Übertragung zu Fuß
abbilden wollte. Ich denke ich kann auch nachvollziehen, was du mit dem
Code bezwecken willst, was ich hier kurz zusammenfassen möchte, um
Missverständnisse auszuschließen:
1.Block: Register Reset
->Alle Register auf Default Value
2. Block
-> Default Value von Register 0x0A auslesen
3. Block
-> Default Value von Register 0x0B auslesen
das ganze hab ich jetzt einfach mal auf den Nano geladen.
ich bekomme allerdings "falsche" Default Werte zurück. Sie Variieren
schon mal zwischen den beiden Registern, was schon mal sehr gut ist,
weil ich bisher immer nur 0xFF zurück bekommen habe, allerdings bekomme
ich für das
0x0A Register: 0xEC
0x0B Register: 0xFC
nach meinem Datenblatt sollten es aber 0x76 und 0x70 sein.
Übersehe ich was?
Was sind die Rückgabe Werte die du bekommst?
-----------------------------
Zum Thema Pull-Up Widerstände, kann ich eurer Diskussion zumindest
folgen. Ich bin eben im Datenblatt des Atmega328P auch auf diese Stelle
gestoßen.
Hier heißt es, dass die externen Pull-Up Widerstände nötig sind. (Wird
aber ein paar Seiten weiter wieder relativiert und es heißt, dass für
manche Anwendungen auch die internen Pull-Up Widerstände genutzt werden
können).
Da hätte ich eine Verständnis Frage: ich war bislang immer der Meinung,
dass Pull-Up Widerstände nur wichtig sind, wenn der Pin als Eingang
konfiguriert ist. Ist das ein Fehlglaube?
Danke euch
Hallo,
David D. schrieb:> Glücklicherweise habe ich noch einen unbenutzten Nano gefunden, mit dem> ich das ganze zum laufen gebracht habe. Ich denke, ob ich jetzt zur> Ansteuerung am Anfang den Nano oder den Uno verwende, sollte keinen> Unterschied machen. (Bitte belehrt mich wenn ich falsch liege)
egal ob Uno oder Nano, ist eben ein Mega328. Die Pinbelegungen der
Boards kannst Du ja vergleichen und die Schaltpläne für beie liegen im
Netz.
Allgemein noch zu ArduinoIDE: Du kannst aus der IDE auch ohne Bootloader
flashen wenn Du einen der gängigen ISP-Programmer hast.
Bei Werkzeuge-> Programmer Deinen Programmer auswählen und dann im Menü
Sketch->Hochladen mit Programmer
Dann brauchst Du auch keinerlei Bootloader auf dem Ziel-AVR.
PullUp sind für die Eingänge soweit richtig. Eingang ist bei I2C das
Ende, was gerade Empfangen will, bei SDA also mal der Master, mal der
Slave.
Deshalb ja OpenDrain damit eine kurzschlüsse gibt wenn einer High setzt
und der andere Low. Bei SCK ist es auch so: ein I2C darf zu jeder Zeit
SCK auf Low halten und so dem Master mitteilen, daß er noch Zeit braucht
(ClockStretching). Deshalb ist I2C auf einem AVR in reiner Software
(also ohne das interne Hardware-TWI ziemlich tricky. Man darf dabei dann
einen Ausgang nie auf PushPull setzen, er ist entweder Eingang (High
dann vom PullUp irgendwo) oder Ausgang/Low.
Gruß aus Berlin
michael
Michael U. schrieb:> Allgemein noch zu ArduinoIDE: Du kannst aus der IDE auch ohne Bootloader> flashen wenn Du einen der gängigen ISP-Programmer hast.> Bei Werkzeuge-> Programmer Deinen Programmer auswählen und dann im Menü> Sketch->Hochladen mit Programmer
Ich habe den AVR Dragon, der ja glaube ich leider nicht dort aufgeführt
ist. Ich habe zwar einen Beitrag gefunden, wo mehrere Dateien der IDE
geändert wurden, um das zu ermöglichen, allerdings nutze ich auf win10
die App von Arduino und da finde ich die Dateien nicht und bin auch
nicht sicher, ob es genauso funktionieren würde.
> Deshalb ja OpenDrain damit eine kurzschlüsse gibt wenn einer High setzt> und der andere Low. Bei SCK ist es auch so: ein I2C darf zu jeder Zeit> SCK auf Low halten und so dem Master mitteilen, daß er noch Zeit braucht> (ClockStretching). Deshalb ist I2C auf einem AVR in reiner Software> (also ohne das interne Hardware-TWI ziemlich tricky. Man darf dabei dann> einen Ausgang nie auf PushPull setzen, er ist entweder Eingang (High> dann vom PullUp irgendwo) oder Ausgang/Low.
Wie genau bekomme ich einen Pin auf OpenDrain? mir sind nur die Modi In
oder Out bekannt. Habe jetzt schon ein paar Beiträge dazu gelesen, aber
werde nicht ganz schlau daraus. Im Datenblatt des OV7670 hab ich etwas
von einem Widerstand in der SDA Leitung gelesen, um die Kurzschlüsse zu
vermeiden. Das erscheint mir aber nicht allzu elegant.
Hallo,
David D. schrieb:> Ich habe den AVR Dragon, der ja glaube ich leider nicht dort aufgeführt> ist. Ich habe zwar einen Beitrag gefunden, wo mehrere Dateien der IDE> geändert wurden, um das zu ermöglichen, allerdings nutze ich auf win10> die App von Arduino und da finde ich die Dateien nicht und bin auch> nicht sicher, ob es genauso funktionieren würde.
Ich habe gerade mal geschaut, ob mein "Drache" noch lebt. ;)
Ich hatte den mal in die IDE eingetragen, war etwas trickreich, habe ich
in der aktuellen inzwischen auch nicht mehr gemacht.
Du kannst auch einfach mit Sketch->Kompilierte Binärdatei exportieren
die von der IDE erzeugten .hex-Files exportieren. Die liegen dann bei
Deinem Projekt im Sketch-Ordner. Einmal mit und einmal ohne Bootloader.
Kannst Du dann ja aus dem Studio ö.ä. mit dem Dragon per ISP
raufschreiben.
Nicht schön, funktioniert aber.
Wenn Du da mehr experimetierst würde ich die ArduinoIDE unbedingt
portabel installieren.
IDE als ZIP runterladen, an einen Ort Deiner Wahl entpacken, IDE NICHT
starten! Im dann vorhandenen Ordner Arduino-1.8.5 einen Ordner
portable
anlegen und dann die IDE starten.
Dann landen alle Dateien, Bibliotheken, Sketchbook usw. in diesem
Arduino-1.8.5 Ordner. Den kann man dann auch koplett umkopieren oder die
IDE von einem USB-Stick direkt an irgendeinem Windows-Rechner starten
und benutzen.
> Wie genau bekomme ich einen Pin auf OpenDrain? mir sind nur die Modi In> oder Out bekannt. Habe jetzt schon ein paar Beiträge dazu gelesen, aber> werde nicht ganz schlau daraus. Im Datenblatt des OV7670 hab ich etwas> von einem Widerstand in der SDA Leitung gelesen, um die Kurzschlüsse zu> vermeiden. Das erscheint mir aber nicht allzu elegant.
Was hast Du vor? Wenn Du die TWI-Hardware des AVR nutzt muß Dich nichts
davon interessieren, daß erledigt die Hardware komplett alleine.
Nur wenn Du TWi/I2C komplett von Hand programmieren willst mußt Du
diverses beachten. habe ich auch schon gemacht, in ASM als die AVR noch
keine TWI in Hardware hatten. Ist aber viele Jahre her...
Ob Du mit der OV7670 jetzt aus der Arduino-IDE redest oder on Du Dir
eine I2C-Bibliothek in C suchst und im Atmel-Studio o.ä. programmierst,
ist relativ egal. Von I2C mßt Du erstmal nur grundsätzliches wissen:
Adresse, Start/RepaetStart/Stop-Condition. Die Wire.h der ArduinoIDE
kapselst aber auch dieses schon. Wire.begin() initialisiert die
I2C-hardware des Mega328 (setzt also taktteiler, TWIEN usw.
beginTransmission schickt Start und Adresse, write schickt Datenbytes.
Das ACK/NACK-Handling erledigen die Funktionen auch mit.
Ich habe auch etwas den Überblick verloren was Du zur Zeit gerade mit
der Kamera anfangen willst...
Gruß aus Berlin
Michael
Vielen Dank für die Informationen. Ja ich werde dann wohl mit dem
fertigen I2C arbeiten, um die Tücken vorerst zu umgehen.
Ja genau deswegen würde ich Vorschlagen erstmal Back-To-Topic.
Das Ziel ist es, die Funktionsweise der Kamera zu verstehen und sie dann
auch zu betreiben. (Dabei möchte ich auf föllig fertige Librarys
verzichten.
Der aktuell 1. Schritt ist, dass SCCB-Interface zum laufen zu bringen.
Sehr gut David, wir sind wieder auf einem Nenner! :-)
Um Software zum laufen zu bekommen muss man natürlich die Hardware
beherrschen, ganz klar. Daher ist der kleine Exkurs zum Thema Arduino IO
Ports schon wichtig.Ich wollte uns ja, durch den Einsatz eines
Pegelwandlers von der ganzen Problematik fern halten. Genauso wie die
ganzen vielen kleinen fiesen Details zum I2C Interface.
Kurz gesagt habe ich gestern mal einen Versuchsaufbau unternommen und
festgestellt das man schon mit externen Pullups arbeiten kann. Im Grunde
macht man das dann so: Solange der Port unprogrammiert ist, ist er
Tristate. Dann programmiert man den Pin als Eingang, schreibt aber
vorher auf den Port eine 0. Dies „entfernt“ den internen Pullup
Widerstand. In Folge ist der Ausgang Opendrain, also offen und der
externe Pullup zieht die Leitung auf den gewünschten Spannungspegel. Nun
kann man durch ändern der Datenrichtung im DDR Register von Eingang aus
Augang dafür sorgen das die Ausgangsstufe auf GND schaltet. Das Ergebnis
ist klar, oder? ;-)
So könnte man auf einen Pegelwandler verzichten. Dieses Prinzip könnte
man auf jeden Port anwenden, also auch auf CLK und Daten. Macht man in
der Programmierung aber irgendwo einen Fehler, oder nutzt eine Library
wo man nicht genau weiss was sie intern tut, ist es gleich vorbei...
Apropos Library. Jetzt verwendest Du ja keine Arduino IDE und somit auch
keine entsprechenden Libs. Hier müssen wir noch zusammenkommen. Ich habe
mich auf Arduino eingelassen weil der sehr verbreitet ist. Du kannst
Deinem Nano den Bootloader nachflashen, via ISP Port.
Wir können aber auch gern die AVR Umgebung nutzen, dann müssten wir uns
halt um das TWI Interface des Atmega selbst kümmern... geht alles,
bringt uns aber erstmal wieder weiter weg vom Ziel.
Olli Z. schrieb:> Wir können aber auch gern die AVR Umgebung nutzen, dann müssten wir uns> halt um das TWI Interface des Atmega selbst kümmern... geht alles,> bringt uns aber erstmal wieder weiter weg vom Ziel.
Mein langfristiges Ziel ist es, das ganze in der AVR Umgebung, bzw. über
das Atmelstudio zu programmieren. Weil ich dann wirklich nachvollziehen
kann, was welcher Pin wirklich wann macht. Da wir aber wie wir ja schon
festgestellt haben auf verschiedenen Systemen arbeiten, habe ich mir zu
Beginn des Wochenendes die Arduino IDE runtergeladen und eben auch noch
einen auf dieser Umgebung funktionierenden Nano ausgegraben.
Für den Anfang sollte das auch in Ordnung sein. Den Transfer auf AVR
ebene kann man dann ja im Nachgang noch vollziehen.
Damit habe ich mich dann an deinen Test-Code (s.o.) gemacht.
Hiernochmal der wichtige Part:
>zu deinem geposteten Test-Code:>Über das I2C Interface wird das ganze definitiv viel Übersichtlicher als>in meinem bisherigen Programmcode, in dem Ich die Übertragung zu Fuß>abbilden wollte. Ich denke ich kann auch nachvollziehen, was du mit dem>Code bezwecken willst, was ich hier kurz zusammenfassen möchte, um>Missverständnisse auszuschließen:>1.Block: Register Reset> ->Alle Register auf Default Value>2. Block> -> Default Value von Register 0x0A auslesen>3. Block> -> Default Value von Register 0x0B auslesen>>das ganze hab ich jetzt einfach mal auf den Nano geladen.>ich bekomme allerdings "falsche" Default Werte zurück. Sie Variieren>schon mal zwischen den beiden Registern, was schon mal sehr gut ist,>weil ich bisher immer nur 0xFF zurück bekommen habe, allerdings bekomme>ich für das>>0x0A Register: 0xEC>0x0B Register: 0xFC>nach meinem Datenblatt sollten es aber 0x76 und 0x70 sein.>Übersehe ich was?>Was sind die Rückgabe Werte die du bekommst?
Ich habe mittlerweile schon zwei Datenblätter gefunden, in denen
unterschiedliche default Values stehen. Daher würde es mich doch
brennend interessieren, was du für Rückgabewerte hast und falls es
andere sind, die Ursache finden, was bei mir wohl noch falsch ist.
Danke und einen schönen Sonntag :)
Ich lese folgende Werte:
Register 0x0A = 0x76
Register 0x0B = 0x73
Darin soll ja die Produkt-ID stecken. In 0A das MSB (PID) und in 0B das
LSB (VER). Da wirken meine Werte jetzt plausibel, denn die Product-ID
(PID) ist laut Datenblatt 0x76 und die Versions-ID (VER) unterscheidet
sich nur leicht (0x73 anstelle im Datenblatt 0x70).
Was ich noch nicht finde ist die tatsächliche Slave-ID. Im Datenblatt
steht: auf Seite 10 "The device slave addresses are 42 for write and 43
for read.". Leider weder ob das Dezimal oder Hexadezimaladressen sind,
es ist auch anders als in den Arduino Beispielcodes zu finden, da wird
für Read und Write diesselbe Adresse verwendet, nämlich 0x21.
Habe mal zum vergleichen den Sketch angepasst um einfach mal alle
Register damit auslesen und anzeigen zu können. Laut Datenblatt gibt es
nur die Register von 0x00 bis 0xC9.
1
#include"Wire.h"
2
3
voidsetup(){
4
Serial.begin(38400);
5
6
// Generate 8 MHz clock output on Pin "9"
7
pinMode(9,OUTPUT);
8
TCCR1A=((1<<COM1A0));//0x23;
9
TCCR1B=((1<<WGM12)|(1<<CS10));//0x09;
10
TIMSK1=0;
11
OCR1A=0;
12
13
// Reset chip to defaults
14
// (write 0b10000000 into register 0x12)
15
Wire.begin();
16
Wire.beginTransmission(0x21);
17
Wire.write(0x12);
18
Wire.write(0x80);
19
Wire.endTransmission();
20
delay(500);
21
22
// Read out values of all registers
23
for(intadr=0;adr<256;adr++)
24
{
25
Serial.print("Value of 0x");
26
if(adr<0x10)
27
Serial.print("0");
28
Serial.print(adr,HEX);
29
Serial.print(" = ");
30
Wire.beginTransmission(0x21);
31
Wire.write(adr);
32
Wire.endTransmission();
33
Wire.requestFrom(0x21,1);
34
while(Wire.available()==0);
35
while(Wire.available()){
36
intb=Wire.read();
37
Serial.print("0x");
38
if(b<0x10)
39
Serial.print("0");
40
Serial.print(b,HEX);
41
}
42
Serial.println("");
43
}
44
}
45
46
voidloop(){
47
48
}
Und hier mein Ergebnis dazu. Auch ich stelle teils massive Abweichungen
zu den Defaultwerten laut Datenlbatt fest:
Okay, dann hab ich bei mir offensichtlich noch ein Problem. Ich werde
nochmal den Aufbau überprüfen und mich dann nochmal melden, entweder mit
dem gefundenen Fehler oder ein paar Fotografien zur Fehleranalyse mit
euch :D
Edit: Habe den Fehler gefunden... aber es ist mir zu peinlich zuzugeben,
dass ich bei meinem Terminal Programm vergessen habe die Baudrate
anzupassen xD....
Damit bin ich mit dir auf einem Nenner, manche Register zeigen zu deinen
zwar Abweichungen, aber ich habe auch die 76 und die 73 in 0A und 0B
> Was ich noch nicht finde ist die tatsächliche Slave-ID. Im Datenblatt> steht: auf Seite 10 "The device slave addresses are 42 for write and 43> for read.". Leider weder ob das Dezimal oder Hexadezimaladressen sind,> es ist auch anders als in den Arduino Beispielcodes zu finden, da wird> für Read und Write diesselbe Adresse verwendet, nämlich 0x21.
Da kann ich Licht ins Dunkle bringen. Das ist nämlich bei beiden das
gleiche ;-)
nur das im Datenblatt offensichtlich das Lese bzw. Schreib Bit
dazugezählt wird, also das R/W-Bit
Sprich der Aufbau ist ja:
Die ersten 7 Bit sind die Adresse und das 8. Bit ist schreiben/lesen.
Wenn jetzt die Adresse 0x21 ist, man die aber einmal nach Links shiftet
um das 8. Bit noch anhängen zu können erhält man: 0x42 (Multiplikation
mit 2)
jetzt ist das R/W bit beim schreiben 0 sprich wir bleiben bei 0x42 und
beim lesen 1 womit wir bei der 0x43 wären.
Ich hoffe das ist soweit verständlich ausgedrückt.
Hallo,
David D. schrieb:> Da kann ich Licht ins Dunkle bringen. Das ist nämlich bei beiden das> gleiche ;-)> nur das im Datenblatt offensichtlich das Lese bzw. Schreib Bit> dazugezählt wird, also das R/W-Bit> Sprich der Aufbau ist ja:>> Die ersten 7 Bit sind die Adresse und das 8. Bit ist schreiben/lesen.> Wenn jetzt die Adresse 0x21 ist, man die aber einmal nach Links shiftet> um das 8. Bit noch anhängen zu können erhält man: 0x42 (Multiplikation> mit 2)> jetzt ist das R/W bit beim schreiben 0 sprich wir bleiben bei 0x42 und> beim lesen 1 womit wir bei der 0x43 wären.
das ist das "übliche" I2C-Problem. I2C benutzt 7Bit-Adressen in
Bit7...Bit1.
Bit0 ist eben R/W.
Ich kenne genug Datenblätter die es mit R/W als 2x 8Bit-Adresse angeben,
ungefähr genausoviele, die die 7Bit-Adresse angeben und die Bitmaske des
Bytes dazu. Bei der Software ist es sehr ähnlich.
Wird man mit leben müssen.
Gruß aus Berlin
Michael
Oh ja, Danke für die Nachhilfe! :-)
0x43 = 0b0100 0011
0x42 = 0b0100 0010
0x21 = 0b0010 0001
Ja und genau das sind natürlich die "Freuden" wenn man Libs verwendet.
Die wollen einem die Arbeit abnehmen und verursachen dadurch manchmal
erst die Probleme ;-) Aber auch die Datenblätter sind mitunter ganz
schön schrottig, wie in diesem Beispiel.
Zu den Defaultwerten: Keine Ahnung ob die immer so sein müssen wie im
Datenblatt. Aber anscheinend klappt die grundsätzliche Kommunikation und
wir könnten einen Schritt weiter gehen?! (Nur weil Du es nicht explizit
erwänht hast: Hast Du nun den Pegelwandler zwischen den Signalen?).
Als nächstes wäre die Frage was wir als nächstes tun. Normalerweise
würde man jetzt die Betriebsparameter für den Kamerabetrieb übermitteln,
dann den PCLK (Pixelclock) anlegen und Bilddaten am Parallelport
abrufen. Ein netter Test hier wäre erstmal nur die HSYNC- und
VSYNC-Signale zu erfassen und zu zählen. Nach jedem erkannten VSYNC
müssten ja immer eine der Auflösung entsprechende Anzahl HSYNC-Signale
folgen. Die einfach zählen und ausgeben.
Hallo,
@Olli Z. (z80freak):
das kommt nun davon...
Arduino Nano und Pegelwandler und die OV7670 zusammengesteckt,
nur 3,3V/GND/SCL/SDA und XCLK angeschlossen.
Deinen Sketch rauf und gestartet.
Ich könnte jetzt die nächste Liste abweichender Registerwerte anbieten,
mit dem Datenblatt habe ich noch nicht vergleichen.
Value of 0x00 = 0xF9
Value of 0x01 = 0x80
Value of 0x02 = 0x88
Value of 0x03 = 0x00
Value of 0x04 = 0x01
Value of 0x05 = 0x7A
Value of 0x06 = 0xAD
Value of 0x07 = 0x40
Value of 0x08 = 0x7A
Value of 0x09 = 0x01
Value of 0x0A = 0x76
Value of 0x0B = 0x73
Value of 0x0C = 0x00
Value of 0x0D = 0x00
Value of 0x0E = 0x01
Value of 0x0F = 0x43
Value of 0x10 = 0x7F
Value of 0x11 = 0x80
Value of 0x12 = 0x00
Value of 0x13 = 0x8F
Value of 0x14 = 0x4A
Value of 0x15 = 0x00
Value of 0x16 = 0x00
Value of 0x17 = 0x11
Value of 0x18 = 0x61
...
Gruß aus Berlin
Michael
Guten Abend,
mein letzter Post für Heute, versprochen ;-)
also ja ich habe drei Pegelwandler zwischen der SCL,SDA und XCLK.
Nachdem ich mir eben dachte, dass so viele Bauteile ja nicht drauf sind
und man die auch bestimmt selber bauen kann, hab ich mir die
Funktionsweise angeschaut und festgestellt, dass es eine High und eine
Low Seite gibt. (Wie auch bei dir im Eagle zu sehen) Wie der Zufall es
so will, hab ich die das Ganze Wochenende so betrieben, was bei kurzem
Nachmessen eben die Erkenntnis brachte, dass ich die Kamera das ganze
Wochenende an 5V Signalen betrieben habe. Jetzt passt aber alles!
Nachdem ich mir die Signalverläufe von deiner Sketch mit deinen von
meinem AVR-Selbstgebasteltem-Kommunikationsprotokoll verglichen habe,
ist mir aufgefallen, dass ich die Stopp und Start Sequenz zwischen den
beiden 2-Phasen Übertragungen vergessen habe. Kaum sind die drin
funktioniert auch mein Skript im Atmel-Studio und liefert die richtigen
Werte! Das Wochenende war also - dank eurer Hilfe - ein voller Erfolg :)
@Michael
Value of 0x0A = 0x76
Value of 0x0B = 0x73
scheinen wenigstens bei uns dreien alle gleich zu sein. :D der Rest
weicht offensichtlich immer vom Datenblatt ab.
@Olli
Hört sich doch schon mal nach einem Plan an.
Habe mal kurz das Oszi dran gehangen und das sieht schonmal nach nem
vernünftigen Signal aus :)
viele Grüße aus dem Schwabenland
David
Prima, David! Da sind wir doch schonmal einem Problem auf die Spur
gekommen. Die Sache mit den Start Stop Sequenzen ist ja elementar für
I2C, logisch.
Was die „Default“-Werte angeht glaub ich fast das die sich aufgrund
bestimmter Funktionen des Chips sofort wieder ändern. Wenn z.Bl Autogain
für irgendwas eingestellt ist, dann könnte ich mir vorstellen das in dem
dafür vorgesehenen Register zum einstellen der Gain im Automatikmodus
dort der aktuelle, selbst gemessene Wert vom Chip auszulesen ist. Ich
würde die stark abweichenden Defaults erstmal vergessen...
Also, unser Programm soll erstmal die Schnittstelle initialisieren, also
TWI Interface aktivieren, XCLK erzeugen und abfragen ob an Slave ID 0x21
der Wert für Register 0x0A den Wert 0x76 aufweist. In dem Fall haben wir
wohl eine OV7670 dran ;-)
Ist das getan, sollten wir der Kamera einen Reset per Software
verpassen, indem wir in Register 0x12 eine 0x80 (0b1000 0000) schreiben.
Hierbeiminteressiert uns der Rest des Registers nicht, weil es sowieso
resettet wird ;-)
Dann kämen die Kameraparameter... hier gerne Vorschläge!
Zuerst noch ein Wort zur Arbeitsweise der Wire-Lib von Arduino
(https://www.arduino.cc/en/Reference/Wire). Achja, mein Beispielsketch
oben ist wirklich nur ein Beispiel, quick'n'dirty, also bitte nicht als
Referenzdesign nehmen ;-)
Einbinden der Lib wie üblich mit:
1
#include"Wire.h"
Initialisiert wird das I2C-Interface vom Atmega als Master (sonst käme
eine Slave-ID in den Funktionsparameter) so:
1
Wire.begin()
Hierbei werden die Signalleitungen A4 und A5 auf Open-Drain eingestellt
und mit SDA und SCL des I2C-controllers im Atmega verbunden. Die
Übertragungsgeschwindigkeit wird (Prozessortaktabhängig durch Teiler)
auf 100 kHz eingestellt und dann mittels TWEN-Bit aktiviert.
Im Prinzip gibt es auch ein "Wire.end()" was das alles wieder
zurückdreht. Das werden wir aber wohl nie aufrufen...
Eine Übertragung sieht so aus, das man eine neue Transmission beginnt,
die zu übertragenden Werte festlegt und startet. Etwas umständlich, aber
naja. Das sieht dann grundsätzlich immer so aus:
1
Wire.beginTransmission(0x21);
2
...
3
Wire.endTransmission();
Wie wir gelernt haben wird die Slave-ID (hier die 0x21) als 7-Bit Wert
angegeben. Das Write-Bit setzt die Lib selbstständig. eine
"Transmission" ist immer eine schreibende Operation.
Nun gibt es bei SCCB den 3-Phase-Write. Dieser besagt das 3 Bytes
hintereinander zum OV-Chip übertragen werden. Um z.B. den Wert eines
Registers zu ändern genügt dies:
1
Wire.beginTransmission(0x21);
2
Wire.write(address);
3
Wire.write(value);
4
Wire.endTransmission();
Um den Wert eines Registers auszulesen sendet man nur die
Register-Adresse und lauscht anschließend am Bus bis Daten kommen:
1
Wire.beginTransmission(0x21);
2
Wire.write(address);
3
Wire.endTransmission();
4
Wire.requestFrom(0x21,1);
5
while(Wire.available()==0);
6
while(Wire.available()){
7
charc=Wire.read();
8
...
9
}
Der erste Teil löst einen 2-Phase-Write aus und schreibt nur Slave-ID
und Register-Adresse die man lesen möchte. Das nachfolgende
"requestFrom()" löst einen 2-Phase-Read aus. Dieser übermittelt die
Slave-ID (erster Parameter) und die Anzahl der zu lesenden Bytes
(zweiter Parameter im Funktionsaufruf).
Jetzt müssen wir warten bis die Daten vom Slave im Eingangspuffer des
I2C-Controllers stehen. Hierfür ist die erste Dummy-While-Schleife mit
"Wire.available() == 0". Ja, das ist unsauber, weil es die
Programmausführung blockiert und sich der Atmega hier aufhängen würde,
käme nie eine Antwort vom Slave. In der Realität würde man hier eher
Events bevorzugen und mittels "Wire.onReceive(handler)" einbauen.
Im Prinzip könnte man sich die nachfolgende While-Schleife um
"Wire.read()" sparen und durch ein einzelnes read ersetzen, weil wir ja
genau ein Byte angefragt haben. Das ist hier nur zur Sicherheit, falls
der Client doch mal mehr oder weniger Bytes sendet als erwartet.
Um anstelle von Bytewerten mit Register- und Wertenamen arbeiten zu
können, sollten wir das benötigte per "#define" Deklaration bekannt
geben. Z.B.:
1
#define OV7670_I2C_ID 0x21
2
#define OV7670_PID 0x76
3
#define OV7670_COM7 0x12
4
#define OV7670_RESET 0x80
So, das müsste im groben und ganzen alles sein was wir zur Kommunikation
mit dem OV-Chip benötigen. Hab ich was vergessen?
Hallo,
Olli Z. schrieb:> Um anstelle von Bytewerten mit Register- und Wertenamen arbeiten zu> können, sollten wir das benötigte per "#define" Deklaration bekannt> geben. Z.B.:
und wenn Du jetzt "faul" bist, schau mal in meinen Post oben vom
23.03.2018 08:58 rein...
https://github.com/ComputerNerd/ov7670-no-ram-arduino-uno
und dann schau dort in die ov7670.h
Selbstverständlich kann man es auch komplett selbst anlegen. Hängt von
Erfahrung, Zeit und der eigenen Art zu Lernen ab.
Früher (tm) habe ich es öfter bei meinen Bastelein machen müssen, weil
nichts dafür zu finden war. C64 ASM und Videotextdecoder (SAA5246).
Zum AVR bin ich wegen des MAS3507 (MP3-Decoder) gekommen, das war
1999...
Zu Deiner Analyse der Wire.h: ich habe sie nur benutzt und auf die
Funktion vertraut. Einen grund reinzuschauen hatte da konkret nicht.
Das viel Arduino-Libs blokierend sind liegt am Konzept. Natürlich kann
man ein Event-Handling mit Interruptsteuerug auch mit den
Arduino-Klassen machen.
PS: vielleicht als I2C-Ergänzung: die Lib muß natürlich auch das
ACK/NACK erledigen. Bei Wire.requestFrom(0x21, 1); muß ja z.B. nach
Senden von Adresse usw. ein RepeatStart statt Stop bei I2C geschickt
werden wenn danach gelesen werden soll.
Gruß aus Berlin
Michael
Habe jetzt erstmal die Pixel pro Zeile gezählt.
Da bekomme ich immer zwischen 479 und 480 Pixel raus.
vielleicht ist mein senden an den UART zu langsam, sodass ich den ersten
Pixel verpasse.
Zur Vorgehensweise würde ich als erstes Versuchen die Frequenz runter zu
nehmen, also PCLK zu verringern und zu schauen, ob es Wirkung zeigt.
Verstehe ich es richtig, dass dann auch die V-Sync und HREF Frequenzen
runter gehen?
Die nötigen Register hierfür wären 0x11 und 0x6B, wobei ich letzteres
nicht ganz verstehe.
Wir sollten kurz das Pinout klären, damit wir auch auf einem Nenner
bleiben :-) Das Problem beim Nano ist, das nur relativ wenig IO-Pins zur
Verfügung stehen. Leider haben wir nichtmal einen kompletten 8-Bit Port
für die Videodaten zur Verfügung. Port D ist mit 2 Bit am UART und fällt
damit flach, sonst haben wir keine Debug-Schnittstelle. Einzige
Alternative wäre hier SoftSerial und zwei andere Pins nehmen. Dann
müsste man den Nano aber wohl besser über ISP flashen.
Habe das jetzt erstmal so vorgesehen:
1
*OV7670DirArduinoMeaning
2
*3v3<-3V3Vcc(+3,3V)
3
*GND<-GNDGND
4
*SIOC<-A5SCL(I2Cclock)!USELEVEL-SHIFTER!
5
*SIOD<-A4SDA(I2Cdata)!USELEVEL-SHIFTER!
6
*XCLK<-D2System-Clock!USELEVEL-SHIFTER!
7
*RESET<-3V3Resetfixedfortesting
8
*PWDN<-GNDPower-Downfixedfortesting
9
*HREF->A6StartofnewlineinVideoframe
10
*VSYNC->A7StartofnewVideoframe
11
*PCLK<-D3Pixelclock!USELEVEL-SHIFTER!
12
*D0->A0VideodataLSB
13
*D1->A1Videodata
14
*D2->A2Videodata
15
*D3->A3Videodata
16
*D4->D4Videodata
17
*D5->D5Videodata
18
*D6->D6Videodata
19
*D7->D7VideodataMSB
Ich hab das Datenwort in ein low- und high-nibble geteilt und damit es
einfach einzulesen ist, das lower auf Bit 0-3 von Port C (A0-A3) und das
higher auf Bit 4-7 von Port D (D4-D7). So müssen wir nur beide Ports
lesen, maskieren und oder-verknüpfen.
Guten Morgen,
ich verstehe deinen Einwand nicht.
Am Nano sind doch noch mehr Pins nach außen geführt als beim UNO oder?
Ich würde es sehr begrüßen, wenn wir die Pins nehmen, die auch beim UNO
verfügbar sind, damit man das selbe Programm auf beiden Boards nutzen
kann:
Habe an deinem Plan mal ein paar Anpassungen vorgenommen:
* OV7670 Dir Arduino Meaning
* 3v3 <- 3V3 Vcc (+3,3V)
* GND <- GND GND
* SIOC <- A5 SCL (I2C clock) !USE LEVEL-SHIFTER!
* SIOD <- A4 SDA (I2C data) !USE LEVEL-SHIFTER!
* XCLK <- D2 System-Clock !USE LEVEL-SHIFTER!
* RESET <- 3V3 Reset fixed for testing
* PWDN <- GND Power-Down fixed for testing
* HREF -> A0 Start of new line in Videoframe
* VSYNC -> A1 Start of new Videoframe
* PCLK <- D3 Pixel clock !USE LEVEL-SHIFTER!
* D0 -> D8 Videodata LSB
* D1 -> D9 Videodata
* D2 -> D10 Videodata
* D3 -> D11 Videodata
* D4 -> D4 Videodata
* D5 -> D5 Videodata
* D6 -> D6 Videodata
* D7 -> D7 Videodata MSB
D8-D11 wäre dann der PORTB 0-3
und D4-D7 wäre PORTD 4-7
Damit verlieren wir nur den MOSI pin. Aber brauchen wir den?
Weiterhin habe ich HREF und VSYNC auf A0 und A1 geholt, weil es A6 und
A7 auf dem UNO nicht nach außen geführt gibt.
Bist du damit einverstanden oder übersehe ich was?
lg. David
Hallo,
A6 und A7 sind beim Mega328 nur ADC-Eingänge, sie haben keine digitalen
I/O-Funktionen. Insofern ist ohnehin Deine Version sinnvoll.
Könntest Du Deinen Source komplett als Archiv hier anhängen?
Ich würde mit den Stand gern ein wenig "mitspielen", nur aus Neugier und
weil die Hardware nun sowieso hier rumliegt.
Gruß aus Berlin
Michael
kann ich machen, wenn ich zuhause bin. Noch eine Frage: Warum muss PCLK
über einen Level-Shifter gehen? der Takt wird doch von der Kamera
vorgegeben oder? den Lese ich doch nur aus?
Hallo,
Danke, hat keine Eile, ich spiele noch mit meiner alten DC3840 am ESP32
weiter, die macht auch noch nicht, was soll.
Bei PCLK stimme ich Dir nach kurem Blick ins Datenblatt der OV7670 zu,
ist Ausgang, braucht also keinen Levelshifter.
Gruß aus Berlin
Michael
David D. schrieb:> Am Nano sind doch noch mehr Pins nach außen geführt als beim UNO oder?
Du hast recht!
Das mit dem PCLK hatte ich falsch verstanden und habs unten im Pinout
korrigiert. Ist aber auch logisch, auf die "Frequenz" der Daten haben
wir ja keinen Einfluss. Evtl. über die Auflösung. Leider kann man die
beim OV7670 nicht frei definieren, sondern nur zwischen VGA, QVGA und
noch was exotischem wählen. Ich glaub das kleinste ist QVGA mit 320x200.
Mit Deinem Pinout habe ich folgendes Problem: Zur Erzeugung des XCLK
habe ich PWM verwendet. Das geht bis max. 8MHz was aber funktioniert. Du
wolltest das per FUSE machen, was man in der Arduino-IDE aber nicht so
ohne weiteres einstellen kann. Wenn wir bei PWM bleiben wollen, dann
müssen wir nur D2 und D3 vertauschen und schon gehts :-) Man könnte auch
den PCLK auf A2 legen, dann wär das mit den anderen Signalen in einem
Register, was vielleicht auch nicht blöd ist.
Hier mein Korrekturvorschlag:
1
*OV7670DirArduinoMeaning
2
*3v3<-3V3Vcc(+3,3V)
3
*GND<-GNDGND
4
*SIOC<-A5SCL(I2Cclock)!USELEVEL-SHIFTER!
5
*SIOD<-A4SDA(I2Cdata)!USELEVEL-SHIFTER!
6
*XCLK<-D3System-Clock!USELEVEL-SHIFTER!
7
*RESET<-3V3Resetfixedfortesting
8
*PWDN<-GNDPower-Downfixedfortesting
9
*HREF->A0StartofnewlineinVideoframe
10
*VSYNC->A1StartofnewVideoframe
11
*PCLK->A2Pixelclock
12
*D0->D8VideodataLSB
13
*D1->D9Videodata
14
*D2->D10Videodata
15
*D3->D11Videodata
16
*D4->D4Videodata
17
*D5->D5Videodata
18
*D6->D6Videodata
19
*D7->D7VideodataMSB
> D8-D11 wäre dann der PORTB 0-3> und D4-D7 wäre PORTD 4-7
Um ein Datenbyte zu lesen wär dann nur sowas nötig:
1
c=(PORTD&0b11110000)|(PORTB&0b00001111);
> Weiterhin habe ich HREF und VSYNC auf A0 und A1 geholt, weil es A6 und> A7 auf dem UNO nicht nach außen geführt gibt.
Stimmt! Hab ich komplett übersehen, bzw. nicht quer geprüft. A6+A7 sind
Analog-Only und fallen eh flach.
> Bist du damit einverstanden oder übersehe ich was?
Ich glaub wir habens fast ;-)
Hallo,
warum eigentlich PWM und nicht CTC-Mode? Auch da gehen zwar nur 8MHz bei
16MHz Clock aber der wurde ja dafür eingebaut.
Habe jetzt aber nicht nach den Ausgabepins der Timer geschaut.
Gruß aus Berlin
Michael
Olli Z. schrieb:> Mit Deinem Pinout habe ich folgendes Problem: Zur Erzeugung des XCLK> habe ich PWM verwendet. Das geht bis max. 8MHz was aber funktioniert. Du> wolltest das per FUSE machen, was man in der Arduino-IDE aber nicht so> ohne weiteres einstellen kann. Wenn wir bei PWM bleiben wollen, dann> müssen wir nur D2 und D3 vertauschen und schon gehts :-)
Jap sollte kein Problem machen, dann machen wir das so. Das mit der Fuse
geht nur auf D8 also (PB0). Aber das hatte ich eh nur testweise über
einen zweiten Controller gemacht. Also können wir da deinen Vorschlag
übernehmen.
>Man könnte auch> den PCLK auf A2 legen, dann wär das mit den anderen Signalen in einem> Register, was vielleicht auch nicht blöd ist.
Der Vorteil an D3 ist, dass der Pin Interrupt fähig ist. Wenn wir es
also in Zukunft schaffen eventuell die Bilder noch irgendwie zu
verarbeiten, wäre der Interrupt gut, um zwischen drin nichts zu
verpassen.
Das alle Signale auf einem Register liegen ist ja nicht unbedingt
notwendig.
Da erscheinen mir die Vorzüge des Interrupts lukrativer und wir belegen
nicht unnötiger Weise einen analogen Eingang.
Hier ein weiterer Korrekturvorschlag: ;-)
1
*OV7670DirArduinoMeaning
2
*3v3<-3V3Vcc(+3,3V)
3
*GND<-GNDGND
4
*SIOC<-A5SCL(I2Cclock)!USELEVEL-SHIFTER!
5
*SIOD<-A4SDA(I2Cdata)!USELEVEL-SHIFTER!
6
*XCLK<-D3System-Clock!USELEVEL-SHIFTER!
7
*RESET<-3V3Resetfixedfortesting
8
*PWDN<-GNDPower-Downfixedfortesting
9
*HREF->A0StartofnewlineinVideoframe
10
*VSYNC->A1StartofnewVideoframe
11
*PCLK->D3Pixelclock
12
*D0->D8VideodataLSB
13
*D1->D9Videodata
14
*D2->D10Videodata
15
*D3->D11Videodata
16
*D4->D4Videodata
17
*D5->D5Videodata
18
*D6->D6Videodata
19
*D7->D7VideodataMSB
>> D8-D11 wäre dann der PORTB 0-3>> und D4-D7 wäre PORTD 4-7> Um ein Datenbyte zu lesen wär dann nur sowas nötig:
1
>c=(PORTD&0b11110000)|(PORTB&0b00001111);
2
>
richtig, das sollte mit dem Maskieren eigentlich recht einfach gehen.
>> Weiterhin habe ich HREF und VSYNC auf A0 und A1 geholt, weil es A6 und>> A7 auf dem UNO nicht nach außen geführt gibt.> Stimmt! Hab ich komplett übersehen, bzw. nicht quer geprüft. A6+A7 sind> Analog-Only und fallen eh flach.
Jetzt sind wir hoffentlich schon fast d'accord :-)
@Michael
Ich glaube, dass du da recht hast, aber es war bisher ja nur ein erster
Gedanke und Entwurf von Olli. Aber ich habe es mal in der Liste der zu
behandelnden Punkte geschrieben.
Ich habe jetzt mal einen Test zum Schreiben von einem Register gemacht.
Ich habe in das CLKRC-Register (Adresse:0x11) das Bit 7 auf 0 gesetzt
und die Bits 0-4 auf 1 um einen Prescaler von 16 zu erhalten.
Damit ist es mir dann tatsächlich gelungen die PCLK von 16Mhz auf 500KHz
zu drosseln. Erfreulich war, dass auch die Frequenz von HREF linear
gesunken ist.
bei 16 MHz PCLK lag die Frequenz von HREF bei 10,2KHz.
bei 500 KHz PCLK lag sie nur noch bei 322 Hz.
Damit könnten wir es sogar schaffen, die Bild Daten testweise mal über
den Serial Port an den PC zu übertragen. Oder verkalkulier ich mich da
grade?
David D. schrieb:> Der Vorteil an D3 ist, dass der Pin Interrupt fähig ist. Wenn wir es
Gutes Argument. Das wäre bei der Verarbeitung der PCLK sicher hilfreich.
Sehe grad das ich D3 in meinem Pinout zweimal geschrieben hab.
Aber wo wir grad bei Interrupts sind, viellecht setzen wir erstmal
nochmal da an, bevor wir das Pinout festzurren.
Wir müssen ja PCLK (24 MHz laut Datenblatt), HSYNC (ca. 32 kHz) und
VSYNC (50-60 Hz) verarbeiten. Ich würde vorschlagen wir tasten VSYNC ab
bis wir einen Bildstart erkennen und setzen ein Flag. Bei jedem HSYNC
müssen wir eine Bildzeile einlesen. Dafür brauchen wir soviel Power vom
kleinen Atmega das wir vermutlich zu nichts anderem kommen werden?! Das
wäre doch was für den Interrupt. Den PCLK können wir für den Interrupt
eh nutzen, da er viel zu schnell ist.
Bitte Vorschläge hierzu :-)
P.S. An alle die ab jetzt erst mitlesen die Info: Wir wollen keine
fertigen Lösungen sondern unsere eigene erarbeiten. Warum? Um genau auf
all die vielen kleinen Details zu kommen die es bei einem solchen Design
zu beachten gilt :-)
Michael U. schrieb:> warum eigentlich PWM und nicht CTC-Mode? Auch da gehen zwar nur 8MHz bei> 16MHz Clock aber der wurde ja dafür eingebaut.> Habe jetzt aber nicht nach den Ausgabepins der Timer geschaut.
Ich muss gestehen das ich da nicht somtief drin bin wie Du. Könntest Du
mir das Konzept kurz erläutern?
David D. schrieb:> Ich habe jetzt mal einen Test zum Schreiben von einem Register gemacht.> Ich habe in das CLKRC-Register (Adresse:0x11) das Bit 7 auf 0 gesetzt> und die Bits 0-4 auf 1 um einen Prescaler von 16 zu erhalten.
Dein Forscherdrang in allen Ehren, aber ich glaube wir müssen uns
darüber verständigen welche Ziele wir in welcher Reihenfolge verfolgen
und konsequent durchhalten. Sonst glaube ich, verzetteln wir uns ganz
schnell und jeder will grad was anderes ;-) Nicht böse gemeint, ich will
das hier nur zusammenhalten... aber es ist Dein Thread!
Eigentlich haben wir Schritt 1 doch gut geschafft, das Kommandointerface
zur Kamera. Nun waren wir am Dateninterface. Hier sollten wir doch
zunächst überlegen wie und wo wir die erhaltenen Bilddaten
zwischenspeichern und zur Ansicht an den PC übertragen. Selbst in
kleinster Auflösung mit 320x200 Bildpunkten und im YUV-Farbmodell
benötigten wir bei 25 Bildern/s einen Datendurchsatz von ca. 4,6 MB/s.
Standardmäßig haben wir nur die UART-Übertragung zum PC, also
Echtzeitvideo dürfte da schonmal ausscheiden.
Das Problem ist, das wir im Arduino nicht genügend Speicher für ein
ganzes Bild haben. Selbst mit 8-Bit s/w würden wir schon 512kb
benötigen. Wir müssen also beim einlesen in Echtzeit zum PC streamen. Da
hab ich noch keine Ahnung wie wir das hinbekommen...
Hallo,
@Andreas S. (igel1): das waren am Anfang des threads auch meine
Gedanken, ich habe mal kurz mit der OV7670 am ESP32 rumgespielt.
Olli Z. schrieb:> P.S. An alle die ab jetzt erst mitlesen die Info: Wir wollen keine> fertigen Lösungen sondern unsere eigene erarbeiten. Warum? Um genau auf> all die vielen kleinen Details zu kommen die es bei einem solchen Design> zu beachten gilt :-)
Ich finde das sehr gut, findet man kaum noch, so habe ich mit µC mal
angefangen. Keine Ahnung davon, 1979 einen MC6800 (8Bit), 512Byte Ram,
einen MC6820 (2x 8Bit I/O) bekommen. Befehlssatz und Beschaltung aus
einem Motorola-Handbuch im Lesesaal das Staatsbibliothek der DDR
abgemalt...
Das ging auch für Normalsterbliche ohne Probleme, für Kopien hätte man
aber Student einer passenden Fachrichtung sein und für Ausleihen einen
Schrieb der Uni haben müssen. Der Rest war DDR-TTL, 7-Segmantanzeigen
usw. gab es durchaus.
Ich habe noch ein wenig im Datenblatt der OV7670 gekramt. Der Ansatz
wäre auch meiner. Mit PCLK auf sinvolle langsame Werte runter. Ich muß
mir die Timingdiagramme noch genauer anschauen mal rechnen wieviel Daten
bei sinnvoll kleiner Auflösung und Format eine Zeile sind. letztlich
entscheide das und der Ram des Mega328 wie man es anpackt. Mit FTDI-USB
habe ich 500kBaud beim Übertragen genutzt, da spielte es aber keine
Rolle, wie langen der AVR zum Bereitsrtellen der Daten brauchte, habe
ich von einem externen Ram per Portzugriffen eingesammelt. War in ASM,
muß ich mal schauen, da habe ich die Zykluszeiten in die Kommentare
geschrieben.
Zum Test müßte man wenigstens eine Zeile ins Ram bekommen und dann zum
PC. Ansonsten kann man vermutlich auf einen Trick von U.Radig mit der
DV3840 von damals zurückgreifen: eine Zeile lesen und rüberschicken,
dann die das Auskesen der Kamera neu starten, die Zeilen mitzählen bis
zur nächsten und die holen usw. Könnte bei der OV7670 auch gehen.
Interrupt würde bei mir höchstens den Anfang festlegen (VSYNC),
Einlesen mit hardwarenaher Schleife, alles andere kosten unnütz Zeit
(INT-Aufruf, Register retten usw.). Der AVR kann in dieser Zeit sowieso
nicht sinvolles anderes machen, also sollte er es auch nicht.
Olli Z. schrieb:> Ich muss gestehen das ich da nicht somtief drin bin wie Du. Könntest Du> mir das Konzept kurz erläutern?
Welcher Timer ist denn dafür genutzt? Bei Timer 1 wäre es MODE2,
PreScaler auf max. internem Takt, OCR0A auf 1 und der zugehörige
Zugehörige Ausgang liefert ein 50:50 Rechteck ab.
Letztlich dürfte es egal sein, ist nur ein Hinweis auf die vorhandene
Funktion im AVR.
Gruß aus Berlin
Michael
Andreas S. schrieb:> Daher hier nur auf die Schnelle meine Quellen, die mir seinerzeit sehr> geholfen hatten:
Vielen Dank für die Links, die können wir sicher noch gut brauchen.
Wir versuchen einfach mal unser bestes :)
Olli Z. schrieb:>Eigentlich haben wir Schritt 1 doch gut geschafft, das Kommandointerface>zur Kamera. Nun waren wir am Dateninterface. Hier sollten wir doch>zunächst überlegen wie und wo wir die erhaltenen Bilddaten>zwischenspeichern und zur Ansicht an den PC übertragen. Selbst in>kleinster Auflösung mit 320x200 Bildpunkten und im YUV-Farbmodell>benötigten wir bei 25 Bildern/s einen Datendurchsatz von ca. 4,6 MB/s.>Standardmäßig haben wir nur die UART-Übertragung zum PC, also>Echtzeitvideo dürfte da schonmal ausscheiden.>>Das Problem ist, das wir im Arduino nicht genügend Speicher für ein>ganzes Bild haben. Selbst mit 8-Bit s/w würden wir schon 512kb>benötigen. Wir müssen also beim einlesen in Echtzeit zum PC streamen. Da>hab ich noch keine Ahnung wie wir das hinbekommen...
Das sehe ich auch so. Das SCCB läuft ja schon mal hervorragend.
Ich finde es gut, dass du mich bremst um uns alle in eine Richtung zu
lenken. Ich bin mir nicht sicher, ob du in meinem Beitrag gelesen hast,
dass ich die PCLK-Frequenz senken konnte. mit allen Prescalern komme ich
dann auf 256KHz von PCLK was uns deutlich mehr Zeit verschafft.
Was jetzt meine Gedanken-Gang wäre:
zunächst einmal mit VSync ein neues Bild detektieren
Dann die Anzahl der Zeilen zählen, bis zum nächsten VSync.
(Das bekomme ich hin mit dem zuverlässigen Wert von 480)
Jetzt wäre der nächste Punkt in einer Zeile die Pixel zu zählen. Den
Counter würde ich mit jeder fallenden Flanke von HREF wieder
zurücksetzten. Hier müsste ich ja (im RGB Mode) für jedes Pixel zwei
Bytes bekommen, sprich zwei PCLK takte. (Ich beziehe mich grade auf
Figure 11 im Datenblatt) Sprich ich müsste 640 * 2 PCLK = 1280
PCLK-Counter pro Zeile bekommen. Hier hänge ich gerade, weil mein
Counter warum auch immer extrem Schwankt zwischen 30 und 60 (Hier
scheine ich vielleicht noch nicht alles verstanden zu haben.
Mein Weitere Plan würde dann wie folgt aussehen, einfach ein Pixel
relativ in der Mitte auszulesen und die Farbdaten in einer Variable
festzuhalten. Dann zu schauen, ob die Farbe passt, oder erstmal ob
Veränderungen auftreten, wenn ich bspw. eine weiße Fläche oder eine
schwarze vor der Linse habe.
Erst wenn das Funktioniert hätte ich mir Gedanken darüber gemacht, wie
ich ganze Bilder zusammensetzte oder Speicher oder übertrage.
Ich lasse mich aber auch gerne eines Besseren belehren :)
@Michael 1979 war mein Vater 17 und ich noch längst nicht in Planung :D
Die Idee mit dem Zeilenweisen Aufbau finde ich gar nicht mal so übel,
wenn wir von einer statischen Aufnahme reden.
lg. David
Michael U. schrieb:> Ich habe noch ein wenig im Datenblatt der OV7670 gekramt. Der Ansatz> wäre auch meiner. Mit PCLK auf sinvolle langsame Werte runter.
100%ige Zustimmung. Evtl. kommen wir da dann an den Punkt wo es
sinnvoller ist den OV7670+FIFO zu nutzen... Da gäbs vielleicht nur noch
die Option eine SD-Card als Zwischenspeicher zu verwenden. Dafür
bräuchten wir aber die SPI-Pins. Mit einem Puffer könnte man ganz
gemütlich nach dem "Schnappschuß" übermitteln.
Dieses Problem müssten aber auch die STM32 haben, denn ein, zwei
Megabyte RAM haben die auch nicht ;-)
> entscheide das und der Ram des Mega328 wie man es anpackt. Mit FTDI-USB> habe ich 500kBaud beim Übertragen genutzt, da spielte es aber keine
Ich verwende nen Nano-Clone und der hat leider keinen Original FTDI
drin. Daher könnte es sein das ich auf die 115kbaud beschränkt bin.
Damit wäre ich bau lausigen 14 kbyte/s. Das ist noch ziehmlich weit weg
von dem was wir bräuchten fürchte ich.
> Zum Test müßte man wenigstens eine Zeile ins Ram bekommen und dann zum
Damit fangen wir doch in jedem Fall an, oder? Auf VSYNC warten und die
ersten 320 (oder 640) Pixel lesen und übertragen.
> PC. Ansonsten kann man vermutlich auf einen Trick von U.Radig mit der> DV3840 von damals zurückgreifen: eine Zeile lesen und rüberschicken,> dann die das Auskesen der Kamera neu starten, die Zeilen mitzählen bis> zur nächsten und die holen usw. Könnte bei der OV7670 auch gehen.
Eine coole Idee :-) An sowas ähnliches hab ich auch schon gedacht, nur
mit Halbbildern, also nur jede 2. Zeile übermitteln oder so. Wenn man
immer ganze Zeilen überträgt spielt auch das Subsampling keine Rolle.
In dieser Richtung könnte man auch horizontal "sparen", also auf Pixel
innerhalb einer Zeile verzichten. Zumindest im YUV-Farbraum sollte man
dann immer zwei aufeinanderfolgende Pixel erhalten, also 2 übertragen, 2
auslassen. Am Anfang wäre RGB zwar einfacher im Bytehandling, aber ich
würde stand jetzt eigentlich beim YUV 4:2:2 bleiben wollen.
> Interrupt würde bei mir höchstens den Anfang festlegen (VSYNC),
Der kommt ja so selten, da sollte man doch drauf warten können, nicht?
Wir können ja immer nur dann ein Bild einlesen wenn wir dazu bereit
sind. In dieser Phase würde ich einfach aufs nächste VSYNC warten und
los gehts...
> Einlesen mit hardwarenaher Schleife, alles andere kosten unnütz Zeit> (INT-Aufruf, Register retten usw.). Der AVR kann in dieser Zeit sowieso> nicht sinvolles anderes machen, also sollte er es auch nicht.
Heißt das, wir sind einer Meinung?
> Olli Z. schrieb:>> Ich muss gestehen das ich da nicht somtief drin bin wie Du. Könntest Du>> mir das Konzept kurz erläutern?> Welcher Timer ist denn dafür genutzt? Bei Timer 1 wäre es MODE2,> PreScaler auf max. internem Takt, OCR0A auf 1 und der zugehörige> Zugehörige Ausgang liefert ein 50:50 Rechteck ab.
Verstehe nur Berlin Hauptbahnhof ;-) Daher meine war meine Bitte: Wie
hängt das alles zusammen? Timer, Modes, Pins, ... ich blicks noch nicht.
Gruß,
Olli
P.S.: Ich finde unsere aktuelle Konstellation (David und Du) wirklich
klasse! Vor allem weil wir uns, etwas untypisch für dieses Forum, weder
anmaulen noch sonst irgendwie im Ton vergreifen. Zudem können wir uns
immer wieder auf einen Nenner bringen. Ich bin echt begeistert und es
macht richtig Spaß!!! :-)
Zum CTC Mode:
Atmega328P Datenblatt Seite 100. (Der Anfangsausschnitt im Anhang)
Im Prinzip wird damit das gleiche erreicht wie mit dem PWM Signal von
dir.
Nur muss man einfach weniger Einstellungen treffen.
Im Prinzip gibst du einfach nur den Timer Wert vor bis zu dem gezählt
werden soll. Wird der erreicht, wird ein Pin (OC0A beim Atmega328P ist
das PD6)getoggelt und der Timer zurückgesetzt.
Somit kannst du relativ einfach ein Rechtecksignal erzeugen.
Was sagst du zu meiner Vorgehensweise?
lg.
David
PS: wie kann ich ein falsches Bildformat wieder löschen?
David D. schrieb:> Andreas S. schrieb:
Ich lese und beantworte immer einen Post nach dem anderen. Manches
überschneidet sich... auch ein Grund warum ich versuche möglichst immer
nur an einem Punkt gleichzeit zu "arbeiten".
>> Daher hier nur auf die Schnelle meine Quellen, die mir seinerzeit sehr>> geholfen hatten:> Vielen Dank für die Links, die können wir sicher noch gut brauchen.> Wir versuchen einfach mal unser bestes :)
Ja, sicher sehr hilfreich. Ich denke auch das wir einiges von unseren
eigenen Erkenntnissen im Dokuwiki hinterlegen sollten/werden, auch für
uns selbst. Hier nochmal mein Vorschlag an Dich und Michael mir mal ne
PN mit eurer Mail zukommen zu lassen, dann lege ich für Euch einen
Account an und ihr könnt dort mit editieren.
> Ich finde es gut, dass du mich bremst um uns alle in eine Richtung zu> lenken. Ich bin mir nicht sicher, ob du in meinem Beitrag gelesen hast,
Danke für die "Blumen", ich verweise nur auf den letzten Absatz meines
vorherigen Posts :-)
> dass ich die PCLK-Frequenz senken konnte. mit allen Prescalern komme ich> dann auf 256KHz von PCLK was uns deutlich mehr Zeit verschafft.
Im Prinzip arbeiten wir ja auch an dieser Stelle. Momentan haben wir
einen Strauß von Möglichkeiten. PCLK wäre einer. Ich bin mir mit der
aktuellen Erfahrung nur nicht sicher ob das verringern der PCLK so ganz
ohne Nebenwirkungen ist. Ich hätte gedacht wenn wir versuchen die
Auflösung, Bildfrequenz, Skalierung (und was weiß ich was die Kamera
noch alles kann) zu verringern, das sich die PCLK automatisch
verkleinert. Wollen wir in diese Richtung mal schauen?
> Was jetzt meine Gedanken-Gang wäre:> zunächst einmal mit VSync ein neues Bild detektieren> Dann die Anzahl der Zeilen zählen, bis zum nächsten VSync.> (Das bekomme ich hin mit dem zuverlässigen Wert von 480)
Ich hätte da einen Vorschlag wie wir mitbekommen können ob der Arduino
schon überlastet ist: Wir arbeiten zeilenbasierend, sprich ein HSYNC
löst via INT die Verarbeitung einer Bildzeile aus. Darin enthalten ist
das auslesen der Pixelwerte, synchron zu PCLK, ggf. der Verarbeitung
dieser (Farbraumumwandlung, Skipping, oder was weiss ich...) bis hin zu
Übermittlung an den PC. Wenn diese Schleife komplett durchläuft ohne das
vorher schon wieder ein HSYNC-INT ausgelöst wird, dann ist alles gut und
wir könnten die Werte "hochdrehen" oder hätten einfach noch Luft für
Bildbearbeitungsfunktionen. Sollten wir jedoch ein Problem erkennen,
könnte man das Programm anhalten und eine LED blinken oder leuchten
lassen.
> zurücksetzten. Hier müsste ich ja (im RGB Mode) für jedes Pixel zwei> Bytes bekommen, sprich zwei PCLK takte. (Ich beziehe mich grade auf
Bei RGB sollten es 3 Byte sein, ein 8-Bit Wert für Rot, einer für Grün
und einer Blau. 2 Byte sind es im YUV-Verfahren.
> Figure 11 im Datenblatt) Sprich ich müsste 640 * 2 PCLK = 1280> PCLK-Counter pro Zeile bekommen. Hier hänge ich gerade, weil mein> Counter warum auch immer extrem Schwankt zwischen 30 und 60 (Hier> scheine ich vielleicht noch nicht alles verstanden zu haben.
Wie gesagt, ich würde noch etwas anders rangehen als sich auf das reine
Pixelzählen zu beschränken. Es geht ja darum ein Bild zu übertragen.
Also erstmal überlegen was man alles machen kann um die Datenflut vom
OV-Chip zum Arduino so weit wie möglich einzudämmen.
Wir sollten vielleicht damit anfangen das Bild nur S/W zu übertragen.
Das ist bei Daten im YUV Farbraum recht simpel, man benötigt einfach nur
das Y-Byte (Luminanz). Das verringert die zu übertragenden Daten
erheblich.
> Ich lasse mich aber auch gerne eines Besseren belehren :)
Deine Ideen sind nicht verkehrt, halt alles nur eine Frage worauf wir
uns einigen. Wie siehst Du das Michael? Ich schlage folgendes vor:
1. Möglichkeiten zur Verringerung der Auflösung/Farbe/PCLK finden
(Datenblatt und Links wühlen)
2. Auf VSYNC warten, Interrupts aktivieren und beim nächsten HSYNC-INT
versuchen sämtliche Daten vom Chip einzulesen.
3. Kollisionserkennung implementieren (kommt während eines INT ein
weiterer)
4. Datenübertragung zum PC (hier brauchst irgend ein "Frontend" auf dem
PC welches die Daten über Serial entgegen nimmt und in eine (Bild)daten
schreiben kann. Entweder was fertiges, oder ein PHP oder Python Skript?
> @Michael 1979 war mein Vater 17 und ich noch längst nicht in Planung :D
Ups, dann bin ich ja quasi der "Opa" hier unter Euch Jungfüchsen ;-))
Olli
Olli Z. schrieb:> Bei RGB sollten es 3 Byte sein, ein 8-Bit Wert für Rot, einer für Grün> und einer Blau. 2 Byte sind es im YUV-Verfahren.
Ich meinte auch RGB555
> Wir sollten vielleicht damit anfangen das Bild nur S/W zu übertragen.> Das ist bei Daten im YUV Farbraum recht simpel, man benötigt einfach nur> das Y-Byte (Luminanz). Das verringert die zu übertragenden Daten> erheblich.
Das klingt gut. Mit dem Format kenne ich mich leider überhaupt nicht aus
und habe es deshalb erstmal gekonnt ignoriert. Ich werde diese
Wissenslücke dann jetzt erstmal füllen.
> 1. Möglichkeiten zur Verringerung der Auflösung/Farbe/PCLK finden> (Datenblatt und Links wühlen)
Ich weiß nicht ob es uns was bringt die Auflösung runter zu schrauben.
Das hilft uns vielleicht bei der Übertragung zum PC aber ich denke
nicht, dass sich das auf die PCLK Frequenz auswirkt sondern einfach die
Frames/sec hochgehen werden.
> 2. Auf VSYNC warten, Interrupts aktivieren und beim nächsten HSYNC-INT> versuchen sämtliche Daten vom Chip einzulesen.
Jap können wir versuchen
> 3. Kollisionserkennung implementieren (kommt während eines INT ein> weiterer)> 4. Datenübertragung zum PC (hier brauchst irgend ein "Frontend" auf dem> PC welches die Daten über Serial entgegen nimmt und in eine (Bild)daten> schreiben kann. Entweder was fertiges, oder ein PHP oder Python Skript?
Ich habe am Samstag eine sehr lange Autofahrt vor mir, da werde ich mal
im Visual Studio was mit c# rumbasteln und uns ein kleines Programmchen
entwerfen, dass das vielleicht kann. (eventuell schaff ich es ja :) )
>> @Michael 1979 war mein Vater 17 und ich noch längst nicht in Planung :D> Ups, dann bin ich ja quasi der "Opa" hier unter Euch Jungfüchsen ;-))
Ist doch Toll, dass wir so ein bunter Haufen sind und uns ergänzen
können.
Olli Z. schrieb:> P.S.: Ich finde unsere aktuelle Konstellation (David und Du) wirklich> klasse! Vor allem weil wir uns, etwas untypisch für dieses Forum, weder> anmaulen noch sonst irgendwie im Ton vergreifen. Zudem können wir uns> immer wieder auf einen Nenner bringen. Ich bin echt begeistert und es> macht richtig Spaß!!! :-)
Das kann ich nur unterstreichen. Als Gelegenheits-Mitleser möchte ich
Euch allein dafür ein Kompliment machen: es ist sehr angenehm, diesen
Thread zu lesen. Hier gibt's ein Ringen um die Sache und einen
respektvollen Umgang miteinander - so macht Elektronik (und überhaupt
das Leben im Ganzen) Spaß. Weiter so!
Ich würde ja soooo gerne mitmachen, aber ich habe vermutlich erst in
einigen Wochen wieder Zeit fürs Hobby. Ich kann Euch also nur ein paar
Tipps aus meinem wochenlangen Kampf mit dem OV7670 geben - so lange
hat's gebraucht, bis es halbwegs an meinem STM32 lief (dummerweise habe
ich auch schon vieles wieder vergessen).
Tipp Nr.1: alle Gedanken, die Ihr Euch gerade macht (vom Interrupt, bis
zu den anzusprechenden SCCB-Adressen), hatten auch andere, die sich mit
dem OV7670 beschäftigt haben. Und diese anderen haben ebenfalls Wochen
und Monate investiert.
Ich habe irgendwann für mich beschlossen, dass ich meinen Stolz, alles
selber herauszufinden, über Bord werfe und von den Erfahrungen dieser
anderen profitieren will - zumindest um die Doku-Defizite damit
aufzufüllen. Daher mein Tipp: lest viele Threads und Foren-Beiträge von
Leuten, die die Tortour schon hinter sich haben und spart Euch Eure
Energie für's Wesentliche auf. Fehlende Hersteller-Doku per
Try-and-Error aufzufüllen wird Euch sonst zermahlen (so meine Weissagung
- basierend auf meinen Erfahrungen)
> 100%ige Zustimmung. Evtl. kommen wir da dann an den Punkt wo es> sinnvoller ist den OV7670+FIFO zu nutzen...
Ja - viele andere haben sich das ebenfalls überlegt.
Meiner Meinung nach macht nur die OV7670+FIFO-Variante für einen Aufbau
mit AVR Sinn. Alles andere überfordert den AVR oder es ist schlicht und
einfach heillose Quälerei.
> Da gäbs vielleicht nur noch> die Option eine SD-Card als Zwischenspeicher zu verwenden. Dafür> bräuchten wir aber die SPI-Pins. Mit einem Puffer könnte man ganz> gemütlich nach dem "Schnappschuß" übermitteln.> Dieses Problem müssten aber auch die STM32 haben, denn ein, zwei> Megabyte RAM haben die auch nicht ;-)
Richtig, daher bin ich in meinem aktuellen Projektstand bislang auch
nicht über QVGA (320x240 Punkte) hinausgekommen.
Allerdings kann so ein STM32 trotz ca. 512k RAM auch größere Bilder
speichern. Das hatte ich mir so überlegt:
- ich lassen den STM32 die Zeilen per DMA (bzw. DCMI) in einen
Ringbuffer einlesen
- während also vorne eingelesen wird (DMA bzw. DCMI belasten ja die CPU
nicht), kann ich hinten im Ringbuffer auslesen und jeweils N-Zeilen
jpeg-kodieren. Sobald diese N-Zeilen jpeg-kodiert sind (der STM32F4 hat
dafür auch einen DSP an Bord), ist der entsprechende Teil im Ringbuffer
wieder frei und kann überschrieben werden.
Damit passen dann auch (komprimierte) Bilder mit der vollen
OV7670-Auflösung in den STM32-Speicher. Irgendeiner im Internet hatte
das wohl auch schon einmal hinbekommen.
Aber allein schon bis zum aktuellen Projektstand musste ich erst einmal
PWM, DMA, DCMI, YUV, YCbCr & Co verstehen und beherrschen. Hat ein
bißchen gedauert.
Der nächste Schritt wird dann JPEG und DSP sein - man braucht dafür
einen wirklich langen Atem (insbesondere wenn's nur Hobby ist) - ich
drücke Euch daher insbesondere die Daumen, dass Euch zwischendurch nicht
die Puste ausgeht.
Weiterhin noch viel Spaß und Erfolg!!
Viele Grüße
Igel1
PS:
- Um überhaupt die eingelesenen Bilder testen/sehen zu können, habe
ich ein ILI9346-Display verwendet: kostet ca. 5 € und kann per
SPI (und auch I2C ??) vom MC angesteuert werden.
Ist super-einfach und unkompliziert im Umgang.
Gängige Module haben sogar auch eine SD-Card-Slot auf der Platine.
Vielleicht wäre das auch etwas für Euch.
- Per UART an den PC senden, geht natürlich auch, ist aber auf die
Dauer zu nervig (weil zu langsam). Insbesondere, wenn's ans
Register-Austesten geht. Da will man nicht jedesmal 1 Minuten warten,
bevor man das Ergebnis einer Register-Veränderung auf dem Schirm
sieht.
- Letzter Tipp: lest Euch unbedingt meine ersten 2 Links aus meinem
letzten Posting durch - diese Seitn sind die "Bibel" für alle OV7670-
Einsteiger.
Noch eine Sache, da unser Projekt offensichtlich etwas umfangreicher und
komplexer wird.
Habt ihr beiden schon Erfahrungen mit GitHub gemacht? Ich nur am rande.
Habe mir grade einmal die vielseitigen Möglichkeiten und Tools
angeschaut, die einem da an die Hand gegeben werden.
Ich denke, da könnten wir unser Projekt besser mit strukturieren,
Aufgaben/Ideen festhalten und diskutieren als hier, wo quasi jeder Post
untereinander kommt.
zusätzlich (bzw. ursprünglich) kann man dort seinen Programm-Code
austauschen, zusammen dran arbeiten und vorschläge unterbreiten.
Auf den ersten Blick wirkt das ganze sehr erschlagend und wenn man der
englischen Sprache nicht ganz so mächtig ist auch erstmal etwas
unverständlich. Aber ich denke, dass wir das ganze damit viel
strukturierter angehen können. Da gäbe es auch eine Wiki-Funktion, wobei
wir da auch bei deinem bleiben können. Du nutzt deins ja noch darüber
Hinaus für andere Projekte.
Schaut es euch mal an uns sagt mir eure Meinung.
Falls ihr begeistert seid, würde ich mal versuchen ein Projekt
aufzusetzen und euch einzuladen.
lg.
David
Andreas S. schrieb:> Ich würde ja soooo gerne mitmachen, aber ich habe vermutlich erst in> einigen Wochen wieder Zeit fürs Hobby. Ich kann Euch also nur ein paar> Tipps aus meinem wochenlangen Kampf mit dem OV7670 geben - so lange> hat's gebraucht, bis es halbwegs an meinem STM32 lief (dummerweise habe> ich auch schon vieles wieder vergessen).
Ich denke den langen Atem werden wir brauchen :D aber ich bin
zuversichtlich. Und werden auch noch einige Wochen brauchen :D
Also du bist dann gerne Willkommen, sobald du die Zeit hast ;-)
Ich habe irgendwann für mich beschlossen, dass ich meinen Stolz, alles
> selber herauszufinden, über Bord werfe und von den Erfahrungen dieser> anderen profitieren will - zumindest um die Doku-Defizite damit> aufzufüllen. Daher mein Tipp: lest viele Threads und Foren-Beiträge von> Leuten, die die Tortour schon hinter sich haben und spart Euch Eure> Energie für's Wesentliche auf. Fehlende Hersteller-Doku per> Try-and-Error aufzufüllen wird Euch sonst zermahlen (so meine Weissagung> - basierend auf meinen Erfahrungen)
Das glaube ich dir und ich bin mir auch sicher, dass wir das von anderen
gesammelte Wissen nutzen werden. Das wir alles selber machen wollen
bezieht sich darauf, dass wir alles verstehen wollen und keine fertigen
Code-Schnipsel verwenden möchten. Das heißt nicht, dass wir die
Scheuklappen aufsetzten und die Erfahrungen Anderer völlig ignorieren :)
Danke für deine Tipps :)
lg. David
Hallo,
David D. schrieb:>>> @Michael 1979 war mein Vater 17 und ich noch längst nicht in Planung :D>> Ups, dann bin ich ja quasi der "Opa" hier unter Euch Jungfüchsen ;-))> Ist doch Toll, dass wir so ein bunter Haufen sind und uns ergänzen> können.
hmmm.. das bezog sich von Daniel auf meinen Kommentar zu meinen
µC-Anfängen 1979...
Ich will nicht zuviel abschweifen:
Als Rentner habe ich jetzt die Zeit hier einfach mal "mitzuspielen".
Meine ersten Videoexperimente war ein "Videograbber" am C64-Userport.
3 Komparatoren für 4 Graustufen und TTL drumrum. Auflösung 160x200, die
war dem C64 Multicolormode geschuldet. Kamera eine TFK500, ohnhin nur
s/w.
Das ging natürlich nur mit einem Standbild, also wie ganz ganz früher:
Start drücken und ca. 3 Minuten nichts bewegen...
Leider habe ich kein so erzeugtes Bild von damals mehr. Meine Kollegen
meinten erkannten den Kopf auf dem Bild zumindest sofort. ;-)
Zum Thema: üblicherweise können diese Cam-ICs einen Snapshotmode, wo sie
das Bild im internen Ram lassen und man es sooft wieder abholen kann wie
man will. Man könnte sonst nie ein sauberes Bild mit anderer als der
Sensorrate auslesen. Die Rate hängt aber direkt vom Sensor-IC,
Lichtempfindlichkeit, interne Umladezeiten usw. usw. ab.
Man hat ja schließlich weder Blende noch Verschluß dran.
Muß ich mal ins Datenblatt der OB7660 schauen.
Ich hör erstmal auf, meine alte DC3840 am ESP32 redet inzwischen mit mir
und schickt mir einen kaputten JFIF-Header???
Die Dc3840 hat vermutlich den Chip der OV7660 drauf, es hängt eben nur
ein OV528 hinten dran als Serial-Bridge.
Bewegte Bilder wid es mit einem Mega328 nicht geben, Snapshots in
640x480 in Farbe alle paar Sekunden sind mit Sicherheit machbar.
3Byte x 320 Pixel wären 960Byte Ram, bei 160 wären es 460 Byte.
Also mit 160x120 zeilenweise einlesen und zum PC schicken.
Sind dann 120 Durchläufe für ein Bild.
Zum Arduino-Nano: der CH340 kann auch 921kBit. Ob er 500 oder 460kBit
kann hängt vom Treiber ab. Gerade mal mein Win7 gefraht: der CP2102 und
der CH340 bieten maximal 128kBit an, der FTDI 921kBit. Das ist aber nur
der Windows-Treiber. Der CH340 (am ESP8266) kann auch 921kBaud.
Nutzt aber alles nur bedingt, der Mega328 mit 16MHz Takt kann zwar
250/500/1000kBaud mit 0% Fehler erzeugen, verkürzt letztlich
Übertragungszeit zum PC, nur beleiben es mangels Ram im Mega328 trotzdem
lauter kleine Häppchen mit Pausen dazwischen zum Lesen der Kamera.
Gruß aus Berlin
Michael
Guten Abend,
ich probiere wieder etwas rum, um unserem Ziel einen Schritt näher zu
kommen.
ich möchte euch auf meinen bisherigen Stand bringen:
Ich versuche das zu realisieren, was wir uns als erstes Teilziel
festgelegt haben:
Das aufnehmen einer Zeile.
dazu habe ich zunächst mehrere Einstellungen in den Registern getroffen,
die zwar Wirkung zeigen, ich die gänzlichen Auswirkungen noch nicht
absehen kann:
CLKRC-Register: 0x0F
COM7-Register: 0x08
COM3: 0x08
COM14: 0x1C
COM10: 0x20
SCALING_PCLK: 0x04
Dabei sei gesagt, dass ich die Register erst auslese und nur die
beabsichtigten Bytes verändere, damit bspw. Reserved Bits nicht
überschrieben werden. Daher kann der tatsächliche Registerwert von
meinen abweichen.
Mit den Einstellungen ergibt sich vollgendes Bild:
- PCLK ist stark gedrosselt, auf ca. 50kHz
- PCLK alterniert nur während HREF-High Pegel aktiv (ansonsten wird PCLK
auf High gehalten)
- Es sollte das QCIF Format eingestellt sein mit 160x120 px (durch
ebenfalls aktiviertes Scaling)
- Das YUV Format sollte aktiv sein.
Was ich vorhabe:
1. die positive Flanke von PCLK erkennen (mittels Interrupt)
2. Dabei die Daten von D0-D8 in ein Byte schreiben
3. Das Byte (zu Testzwecken) in einem Array ablegen
4. so viele wie mögliche Bytes erfassen
Wenn ich mit dem Oszilloskop messe, bekomme ich das Verhalten Von PCLK
und HREF wie vorgestellt hin.
Der Interrupt löst aber nur unregelmäßig aus (obwohl die Flanke von PCLK
auf dem Oszi sichtbar ist). Meistens immer zu V-Sync Signalen, sprich
wenn HREF und somit PCLK länger statisch sind.
Meine Interrupt Routine ist nicht überladen:
1
ISR(INT0_vect){
2
PORTB|=0x20;
3
interruptFlag=true;
4
i++;
5
_delay_ms(1);//eingeführt um ein "übersehen" vom Oszi auszuschließen
6
PORTB&=~(0x20);
7
}
PortB 0x20 ist Pin 13 und da greife ich mir das Signal ab, wenn der
Interrupt ausgeführt wird
Da ich nun wirklich schon mehrere Stunden an diesem Problem sitze,
drängt sich mir die Frage auf, wie schnell denn der externe Interrupt
eigentlich arbeiten kann, und ob es dort ebenfalls max. Frequenzen gibt.
Leider konnte ich nichts finden. Habt ihr da schon Erfahrungen?
lg. David
@David:
bzgl. Interrupt-Routinen, gibt es viele Seiten, die sich mit der
Latenz-Zeit beschäftigen. Evtl. ist die ja schon hinreichend:
Beitrag "Interrupt latency"
Meine AVR-Zeiten liegen leider schon ein paar Jährchen zurück, aber ich
habe vielleicht doch einen sehr praktischen Tipp:
Natürlich kann man die Dauer der ISR-Routine (inkl. dem Overhead zum
Aufruf der ISR-Routine) sauber auf dem Papier ausrechnen. Das bedeutet
aber immer viel Lesen und Nachschlagen.
Ich habe damals oftmals einfach den Debugger genutzt:
Wenn Du das Programm im Debugger laufen läßt, so kannst Du exakt
nachverfolgen, wieviele Zyklen das Einspringen in die ISR und die
Abarbeitung Deiner ISR benötigt.
Und ja, es gibt eine bestimmte Zeit, die ein Pegel anliegen muß, damit
die ISR ausgelöst wird - steht irgendwo im Datenblatt.
Viele Grüße
Igel1
Hi David, offensichtlich müssen wir uns noch zwei grundlegende Techniken
im Zusammenhang mit dem Arduino (Atmega) aneignen: Timer (zur
Clock-Erzeugung) und Interrupts. Darauf basieren die wesentlichen
Komponenten unserer Umsetzung.
Deine Ermittlung mit PCLK finde ich bemerkenswert, denn laut Datenblatt
läge der PCLK immer an, sobald XCLK bereitgestellt wird. Aber vielleicht
sind das eben genau die Dinge von denen Andreas gesprochen hat...
Gelesen hab ich über Timer und Interrupts schon so einiges, angewendet
hab ich die auch schonmal, aber so ein richtig tiefgehendes Verständnis
habe ich auch nicht dafür. Gute Voraussetzungen um hier mal "ganz unten"
zu starten :-)
David D. schrieb:> Wenn ich mit dem Oszilloskop messe, bekomme ich das Verhalten Von PCLK> und HREF wie vorgestellt hin.> Der Interrupt löst aber nur unregelmäßig aus (obwohl die Flanke von PCLK> auf dem Oszi sichtbar ist). Meistens immer zu V-Sync Signalen, sprich> wenn HREF und somit PCLK länger statisch sind.>> Meine Interrupt Routine ist nicht überladen:>
1
ISR(INT0_vect){
2
>PORTB|=0x20;
3
>interruptFlag=true;
4
>i++;
5
>_delay_ms(1);//eingeführt um ein "übersehen" vom Oszi auszuschließen
6
>PORTB&=~(0x20);
7
>}
8
>
>> PortB 0x20 ist Pin 13 und da greife ich mir das Signal ab, wenn der> Interrupt ausgeführt wird>> Da ich nun wirklich schon mehrere Stunden an diesem Problem sitze,> drängt sich mir die Frage auf, wie schnell denn der externe Interrupt> eigentlich arbeiten kann, und ob es dort ebenfalls max. Frequenzen gibt.> Leider konnte ich nichts finden. Habt ihr da schon Erfahrungen?
Erfahrung ja, aber leider liegt meine Atmega-Zeit schon etwas zurück,
daher bitte meine Hinweise mit Vorsicht genießen:
1.) Ein Sprung in die ISR benötigt minimal 4 Takte:
s. Kap. 11.7.1 im Datenblatt:
http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf
ABER: das kannst Du nur erreichen, wenn Du in Assembler
programmierst
und exakt weißt, was Du tust.
Dein C-Compiler wird noch jede Menge Zusatz-Befehle einfügen (vor
allem Register-Push Operationen).
Auch benötigt der Rücksprung aus der ISR nochmals 4 Takte sowie
vermutlich jede Menge Register-Pop-Operationen.
2.) Bei 50kHz PCLK-Frequenz ist eine Periode 20us lang, was immerhin
320 Takten bei 16MHz Prozessortakt entspricht. Müßte eigentlich
ausreichen, um eine ISR sauber auszuführen.
3.) Hier meine Vermutung, was bei Dir passiert:
- Du hüpfst mit der ersten PCLK-Flanke in die ISR und schaltest
dort Deinen Pin13 an.
- Per "interruptFlag=true;" enables Du dann vermutlich Dein
globales Interrupt-Flag, so dass weitere Interrupts akzeptiert
werden - auch während Du noch in der ISR weilst.
Du brauchst das "interruptFlag=true;" vermutlich deshalb,
weil Deine _delay_ms(1) sonst nicht funktioniert.
- Dann rufst Du die Delay-Routine auf. Diese Delay-Routine wird
vermutlich Ihrerseits ebenfalls über Interrupts abgewickelt
werden. Je nach Implementierung wird sie jedoch niemals zu
Ende kommen, weil ja bereits nach 20us die nächste PCLK-Flanke
kommt, die wiederum einen Einsprung in Deine ISR bewirkt.
- Bevor die Video-Zeile zu Ende ist (bei Deinem QCIF also nach
160 x 20us = 3200us) plus 1ms Delay wird Dein Pin 13 also nicht
abgeschaltet werden. Außerdem wurde die ISR zu diesem Zeitpunkt
160x rekursiv aufgerufen - der Rücksprung wird entsprechend
lange dauern ...
Daher mein Tipp:
- Schmeiss unbedingt die Delay-Funktion aus Deiner ISR raus.
Dein Oszi wird ja wohl Signale an Pin13, die > 0,1us lang
sind, locker darstellen können.
- Dann triggerst Du auf dem ersten Oszi-Kanal auf PCLK und
schaust Dir auf dem 2. Oszi-Kanal Pin13 an. So solltest Du
den Delay beim Aufruf der ISR schön sehen können.
Viele Grüße
Igel1
Hallo,
PCLK auf 50kHz, da kommt alle 20µs ein Clock-Impuls.
Bei 17MHz ist die Zykluszeit des AVR 62,5ns, also maximal 320 Takte für
ISR-Aufruf, Abarbeitung und wueder raus. Dann ist aber keinerlei Zeit
mehr, außerhalb was zu machen. Der AVR führt nach verlassen einer ISR
genau einen ASM-Befehl aus wenn schon wieder irgendein Interrupt
ansteht.
ISR(INT0_vect){
> PORTB |= 0x20;> interruptFlag=true;> i++;> _delay_ms(1); //eingeführt um ein "übersehen" vom Oszi auszuschließen> PORTB&= ~(0x20);> }>
1ms Delay geht ja mal garnicht, da sind 50 PCLK vergangen...
Man könnte sich jetzt das ASM-Listing anschauen, das der Compiler
erzeugt.
Wenn die Portzugriffe richtig optimiert (kann der GCC eigentlich), sind
das jeweils 3 oder 4 Takte. Die Umsetzung von interruptFlag=true; und
i++; wird wesentlich ungünster sein, weil der GCC intern C-typisch mit
16Bit-Werten rechnet und das kostet einige Registerschiereien. Dazu
kommt die recht umfangreiche Register-Retterei beim ISR-Aufruf und die
Wiederherstellung beim Verlassen in C.
Ich hoffe, ich habe jetzt auf die Schnelle nicht falsch gerechnet...
Ich hatte oben schon irgendwo angedeutet, das ich den Weg nicht für
machbar halte. Bei VSync in die ISR und dann per Busy-Loop auf H-Sync
warten. Dann PCLK direkt abfragen und bei jeder Flanke die Daten
einlesen und wegspeichern. Das in der ISR der AVR nur mit dem Kram
beschäftigt ist, ist hier nur von Vorteil, außerdem ist es nur für genau
ein Bild (oder beim Test erstmal eine Zeile). Wie man dann mit den Daten
umgeht ist sowieso noch zu klären...
PS: meine alte DC3840 redet inzwischen am ESP32 mit mir, prinzipiell
auch am ESP8266. Diese Camera hat vermutlich sogar den gleichen
Bildsensor, man kommt wegen ser seriellen Bridge und deren Firmware
allerdings nicht an dessen Register ran. Leider hat sie im Gegensatz zur
OV7670 eine miserable Optik.
Diese Kamera lief irgendwann um 2008 schonmal mit einem Webserver von
U.Radig auf einem Mega32 mit 14,xxx MHz Takt.
Ich habe sie mal schnell mit einer USB-Verlängerung auf den Balkon
geklemmt, so als Anreiz. ;-)
Gruß aus Berlin
Michaeö
Michael U. schrieb im Beitrag #53744
> Hallo,>> PCLK auf 50kHz, da kommt alle 20µs ein Clock-Impuls.> Bei 17MHz ist die Zykluszeit des AVR 62,5ns, also maximal 320 Takte für> ISR-Aufruf, Abarbeitung und wueder raus. Dann ist aber keinerlei Zeit> mehr, außerhalb was zu machen.
Im großen und ganzen stimme ich Michael ja zu, nicht aber beim oben
Zitierten. (Statt 17MHz meinte Michael sicherlich 16MHz - aber das war
bestimmt nur ein kleiner Typo und ist nicht Gegenstand meiner Kritik.)
Der Punkt, um den es geht, ist folgender: ich bin der Meinung, dass der
Prozessor bei 320 Takten zwischen zwei PCLK-Flanken nach der Abarbeitung
einer kurzen ISR noch >200 Takte Zeit für andere Dinge haben sollte.
David wird das hoffentlich in Kürze bestätigen, wenn er mit angepaßtem
ISR-Code hier neue Ergebnisse posten wird.
Viele Grüße
Igel1
Hallo,
Andreas S. schrieb:> Der Punkt, um den es geht, ist folgender: ich bin der Meinung, dass der> Prozessor bei 320 Takten zwischen zwei PCLK-Flanken nach der Abarbeitung> einer kurzen ISR noch >200 Takte Zeit für andere Dinge haben sollte.
ist gut möglich, habe ich nicht weiter ins Detail gerechnet.
Ich wollte auch mehr darauf hinaus, daß es für das konrete Projekt nicht
wirklich etwas zwischen dem Einlesen von 2 Pixeln zu tun gibt.
Wenn man also eine Zeile komplett in einer HSync-ISR einliest und
zwischenspeichert, erspart man sich mögliche Timingprobleme mit einer
PCLK-ISR erstmal ganz.
Man muß zum Üben und Testen nicht alle Probleme gleichzeitig lösen
wollen. ;)
Gruß aus Berlin
Michael
... ich hoffe, der Thread schläft nicht ein, bin doch zu neugierig,
wie's weitergeht.
Habe mir die HW-Aussstattung so eines Atmega328p vorhin nochmals
genauer angeschaut ... puhhh, ganz schön knapp ...
Das war für mich seinerzeit der Grund, auf ARM umzusteigen und
das wäre auch mein Rat an Euch:
OV7670 und ATmega - das paßt einfach nicht gut zusammen.
Früher oder später wird Euch die HW-Beschränkung frustrieren,
weil Ihr maximal die Pixel bei arg reduzierter Auflösung einlesen und
mehr oder weniger 1:1 irgendwohin weiterschieben könnt.
Wenn ich die Zeit betrachte, die ich benötigt habe, um vernünftige
Bilder aus der OV7670 herauszubekommen, so kann man sich in dieser
Zeit auch schon etwas vom ARM-Prozessor beibringen.
Und daraus ergibt sich meine Anregung an Euch: überlegt Euch, ob es
Sinn machen könnte, ein paar Wochen Einarbeitung in ARM-Technologie
zu stecken, um dann mit ca. 10-fach gestärkter Muskelkraft nochmals
an die OV7670 heranzutreten.
Um Euch die Sache schmackhaft zu machen:
Ein STM32F429I-Discovery-Board bekommt man für ca. 20-25 EUR in der
Bucht.
Dort ist neben einem potenten stm32f429-Prozessor auch schon ein
ILI9346-Display drauf - optimal zum Experimentieren mit dem OV7670
Und der Prozessor kann (aus dem Kopf geschrieben):
- Läuft auf 3,3V und kann direkt mit OV7670 gekoppelt werden
- Hat 180 MHz Taktfrequenz
- Hat ca. 256 kByte RAM, ca. 1 MB Flash
- Kann DMA (= Daten von A nach B schieben ohne die CPU zu behelligen)
(A oder B können sein: RAM, GPIO, UART, DCMI, SPI, ...)
- kann DCMI (= Kamera-Daten per DMA in RAM-Bereiche schieben)
- hat DSP an Board
- hat unendlich viele IO-Ports
- hat mehr als zwei Hände voller Timer
- hat mehrere unabhängige UART's, I2C's und SPI's an Board
- hat Ethernet, CAN, USB - Controller an Board
- hat sogar irgendwelche LCD-TFT-Controller an Board
- hat mehrere 12-Bit A/D- und D/A-Wandler
... ach ja: und auf dem Board stecken zufällig noch 64MB SDRAM,
Test-LED, Test-Button und ein Beschleunigungs-Sensor.
Oder schaut einfach selbst:
Board: http://www.st.com/en/evaluation-tools/32f429idiscovery.html
Prozessor - Datasheet:
http://www.st.com/resource/en/datasheet/dm00071990.pdf
Prozessor - Reference Manual:
http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf
Und das Beste: so ein ARM-Prozessor kommt mit einem "Hardware-
Debugger" daher - man kann seine Programme also Schritt für
Schritt debuggen - nicht im (buggy Atmel-)Simulator, sondern
nativ auf der Hardware (inkl. Register-Auslesen und Pi-Pa-Po)
Kurzum: ihr bekommt alles, was man sich schon immer gewünscht hat.
Im Gegenzug - das sei nicht verschwiegen - kostet so ein ARM-
Prozessor aber ein paar Wochen Einarbeitungszeit und insbesondere
der Anfang ist etwas hart.
Viele Grüße
Igel1
Hallo,
ich habe nicht vor diese Thread einschlafen zu lassen. Ich verfolge die
Beiträge auch sehr interessiert. Leider bin ich diese Woche sehr
eingespannt und werde erst ab dem Wochenende wieder dazu kommen, meinen
ausführlichen Beitrag zu leisten.
lg.
David
Hallo,
Andreas S. schrieb:> OV7670 und ATmega - das paßt einfach nicht gut zusammen.> Früher oder später wird Euch die HW-Beschränkung frustrieren,> weil Ihr maximal die Pixel bei arg reduzierter Auflösung einlesen und> mehr oder weniger 1:1 irgendwohin weiterschieben könnt.
Man kann die Pixel in maximaler Auflösung (sind ja nur 640x480) einlesen
und kann die irgendwohin schieben (als Webseite wenn man noch einen
ENC28J60 oder was moderneres dranhängt) oder auf eine SD-Karte
speichern.
Was einschränkt: man kann keine Bewegtbilder bekommen, geht mit dieser
Kamera aber sowieso nicht wirklich) und muß etwas Geduld mitbringen
(10-15s um ein Bild in den Webbrowser zu bekommen) und man muß ein paar
egenwillige Wege gehen.
Ich hatte am 02.04.2018 13:42 ein Bild von meiner DC3840 angehängt,
allerdings mit einem ESP32 eingelesen und rübergeschickt.
Genau diese Kamera hing vor vielen Jahre an einem ATMega32 mit dem
ENC28J60 als LAN-IC.
921000Baud von der Kamera und auch kein Ram. Eingelesen in 128 Byte
Häppchen und dem TCP-Buffer in die Hand gedrückt. Wenn das Paket voll
war rausgeschickt usw.
Ziel war nur "es müßte machbar sein".
Natürlich konnte man auch damals schon eine USB-Webcam bemühen, an einen
kleinen PC hängen usw. Das konnte ja sozusagen jeder. ;-)
Sind 10 Jahre seitdem vergangen:
http://www.ulrichradig.de/home/index.php/projekte/uC-kamera> Wenn ich die Zeit betrachte, die ich benötigt habe, um vernünftige> Bilder aus der OV7670 herauszubekommen, so kann man sich in dieser> Zeit auch schon etwas vom ARM-Prozessor beibringen.
Ich nehme an, die OV7660 ist überhaupt nur wieder aufgetaucht, weil es
sonst wohl nichts mehr auf dem Markt gibt, mit dem man überhaupt an
einem AVR o.ä. Chancen hätte.
Wollte ich sowas machen wäre es doch heute ein RasPi Zero W, die
zugehöirge Cam dran und der Viedostream in HD wäre greifbar.
Man wird heute solch ein Kameramodul kaum noch irgendwo wirklich
einsetzen wollen. Weder mit einem ARM noch überhaupt. Zu langsam,
Auflösung zu gering, Lichtempfindlichkeit zu schlecht usw. usw.
Der Sensor der OV7670 ist der, der auch in obiger DC3840 vor 10 Jahren
drin war... Die Optik der OV7660 ist etwas besser und lichtstärker.
Wozu also das Ganze? Man lernt Datenblätter zu lesen, man lernt I2C
kennen, man lernt es, das Zeitverhalten eines System in Hardwarenähe zu
beachten.
Das hilft aber auch auf anderen Systemen bei anderen Aufgaben.
Nimm es als Spaß an der Sache, Zeit bei einer Hobbyaufgabe war noch nie
ein Kriterium.
Ich verfolge das hier interessiert weil ich es schon kenne (und auch
schon kann) und als Rentner etwas Zeit habe.
Wäre doch lusitg (und sinnlos...): OV7670, Mega328, SX1276
(LoRa-Funkmodul) und nach 6-7 Stunden hätte man ein komplettes Bild am
anderen Ende. ;)
Gruß aus Berlin
Michael
Hier ein Beitrag, den ich vergessen hatte, abzuschicken - er
referenziert auf den letzten Beitrag von David.
David D. schrieb:> Da ich nun wirklich schon mehrere Stunden an diesem Problem sitze,> drängt sich mir die Frage auf, wie schnell denn der externe Interrupt> eigentlich arbeiten kann, und ob es dort ebenfalls max. Frequenzen gibt.> Leider konnte ich nichts finden. Habt ihr da schon Erfahrungen?>> lg. David
Zu dem "Overhead", der bei der Interrupt-Verarbeitung anfällt, hatten
Ulrich und ich ja bereits etwas geschrieben.
Nun habe ich nochmals nachgeschaut, wie lange so ein Puls denn anliegen
muss, damit eine Flanke denn auch wirklich einen Interrupt auslöst.
Die Antwort findet sich im Datenblatt des Atmega328p auf S. 53 und S.
54:
http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
Aus Figure 12-1 läßt sich schon erahnen: der Pegelwechsel muss
mindestens 1 CPU-Takt lang anliegen und auf S. 54 wird das nochmals
bestätigt:
". If edge or toggle interrupt is selected, pulses that last longer than
one clock period will generate an interrupt".
Wenn Dein ATmega328p-Schweinchen also mit 16MHz rennt, so können Pulse
mit einer Dauer von 1/16MHz = 0,0625us detektiert werden. Von dort droht
also keine Gefahr.
Das Problem bei einer Bearbeitung über Interrupts wird eher der Overhead
für das Einspringen (min. 4 Takte), das Rückspringen (min. 4 Takte) und
das Sichern bzw. Widerherstellen von N Registern und für ein bißchen
ISR-Code sein.
Man liest von 50-80 Taktzyklen, die dann mal ganz fix futsch sind. Bei
80 Taktzyklen könntest Du also frühestens nach 80 x 0,0625us = 5us die
nächste Taktflanke per Interrupt bearbeiten. Ganz streng betrachtet
kannst Du beim YCbCr422 Format sogar eine Flanke "schludern", weil Du ja
nur die Y-Flanke mitbekommen mußt - aber da wind's dann schon langsam
haarig mit den ganzen Timings.
Das beschränkt Deinen PCLK-Takt auf 1/5us = 200kHz, was wiederum am
unteren Ende der Spaßgrenze liegt, denn:
Gemäß Tabelle 3.3 im Implementation Guide:
http://www.haoyuelectronics.com/Attachment/OV7670%20+%20AL422B%28FIFO%29%20Camera%20Module%28V2.0%29/OV7670%20Implementation%20Guide%20%28V1.0%29.pdf
... kannst Du bei 24MHz PCLK die max. 30 Frames/s erreichen.
Mit 200kHz liegst Du um den Faktor 120 darunter, was Deine Framerate auf
30f/s / 120 = 0,25/s reduziert. Wie gesagt: am unteren Ende der
Spaßgrenze.
Kurzum: Ein Polling-Mechanismus wäre vermutlich besser geeignet, um die
Pixel aus der Kamera in das RAM einzulesen.
Soweit meine 10 Cent ...
Viele Grüße
Igel1
Guten Tag zusammen,
ich hoffe ihr könnt den Tag ebenso sonnig genießen wie ich es tue.
So sitze ich also gemütlich mit meinem Laptop auf dem Balkon und nehme
mir wie versprochen die Zeit, einen ausführlichen Beitrag zu schreiben.
Zunächsteinmal vielen Dank für die vielen Hilfestellungen.
Zu meinem letzten Post:
Ich glaube ich sollte aufhören Nachts noch schnell einen Beitrag zu
schreiben, sondern lieber in Ruhe vollständige Informationen liefern ;-)
Folgendes war mein (vollständiger) Gedankengang:
Ich schaue zunächst, ob neben der ISR-Routine, die den PCLK Peak
detektieren soll, noch Zeit bleibt um in dem Hauptprogramm etwas zu
rechnen/bearbeiten/senden/speichern etc.
Wie ich das vorhabe:
Ich lasse in der ISR-Routine einen Zähler hochlaufen und setzte eine
FLag-Variable die anzeigt, dass ein Interrupt da war. Im Hauptprogramm
frage ich die Flag ab und erhöhe, falls diese Vorhanden ist, einen
zweiten Zähler und setzte die Flag dann wieder zurück.
Wenn ich jetzt im Debugging-Modus bin und Pause drücke, sollten beide
Zähler den gleichen Wert haben, oder der ISR-Zähler maximal eins mehr
haben.
Um einen Überlauf der int-Variablen zu verhindern habe ich noch eine
Grenze festgelegt. Ebenso wollte ich mit dem Zählen erst bei der
nächsten HREF-Periode beginnen, um gleichzeitig zu schauen, ob ich auch
die eingestellt Auflösung (bzw. die erwartete Anzahl an Bytes) erhalte.
Mir ist bewusst, dass eine delay Funktion absolut nichts in einem
Interrupt zu suchen hat (daher habe ich sie jetzt auch wieder raus
genommen). Diese ist nur als letzter Hoffnungsschimmer eingefügt worden,
weil ich verzweifelt gedacht habe, mein Oszi könnte die eventuell
verpassen. (Der Kommentar im Programmcode war anscheinend nicht
ausführlich genug)
Der Verdacht des rekursiven Aufruf gefällt mir ganz gut. Hatte aber auch
zu Beginn und zum Ende der Routine cli() bzw. sei() gesetzt, um diesen
Fall auszuschließen. Brachte aber leider keine Veränderung.
Hier mein Vollständiger Code (allerdings im AVR-Style)(Versuche das die
Tage mal auf Arduino umzumünzen, damit wir wieder auf der gleichen
Plattform sind) Ich hoffe, ihr könnt trotzdem etwas damit anfangen:
1
/*
2
* main.cpp
3
*
4
* Created: 23.07.2017 17:35:15
5
* Author: David
6
*/
7
8
#ifndef F_CPU
9
#define F_CPU 16000000
10
#endif
11
12
#include<avr/io.h>
13
#include<avr/interrupt.h>
14
15
#include"OV7670.h"
16
#include"OV7670.c"
17
18
#include"UART.h"
19
20
21
volatileunsignedinti=0;
22
//unsigned char myBytes[100];
23
boolinterruptFlag=false;
24
intmain(void)
25
{
26
sei();
27
28
UART0_init();
29
OV7670_init();
30
OV7670_checkConnection();
31
32
33
//Reduce frequency of PCLK
34
charReadData=0;
35
charMASK=~0x80;
36
charWriteData;
37
//Read the RCLK Register to get the internal Clock
38
OV7670_read(OV_SCCB_CLKRC,&ReadData);
39
UART0_senden_Byte(ReadData);
40
UART0_newLine();
41
42
//Reduce PCLK by Prescaler
43
OV7670_write(OV_SCCB_CLKRC,0x0F);
44
45
//Check if change succed
46
OV7670_read(OV_SCCB_CLKRC,&ReadData);
47
UART0_senden_Byte(ReadData);
48
UART0_newLine();
49
50
//Change Format to QCIF and YUV
51
OV7670_read(OV_SCCB_COM7,&ReadData);
52
MASK=ReadData&0b01000000;
53
MASK|=0x08;
54
ReadData|=MASK;
55
OV7670_write(OV_SCCB_COM7,ReadData);
56
57
//activate Skaling
58
OV7670_read(OV_SCCB_COM3,&ReadData);
59
ReadData|=0x08;
60
OV7670_write(OV_SCCB_COM3,ReadData);
61
62
//Activate DCW and scaling PCLK enable (neccessary for Divide PCLK) and Divide PCLK by 16
63
OV7670_read(OV_SCCB_COM14,&ReadData);
64
ReadData|=0x1C;
65
OV7670_write(OV_SCCB_COM14,ReadData);
66
67
//deactivate PCLK during HREF Blank
68
OV7670_read(OV_SCCB_COM10,&ReadData);
69
ReadData|=0x20;
70
OV7670_write(OV_SCCB_COM10,ReadData);
71
72
//Scaling PCLK
73
OV7670_read(OV_SCCB_SCALING_PCLK,&ReadData);
74
ReadData&=~(0x0F);
75
ReadData|=0x04;
76
OV7670_write(OV_SCCB_SCALING_PCLK,ReadData);
77
78
//set Variables and Flags
79
i=0;
80
interruptFlag=false;
81
boolHREF_Flag=false;
82
83
volatileintj=0;
84
//Setup interrupt pin
85
EICRA|=(0b00000011);//Interrupt at Int0-Pin at positiv change
86
EIMSK&=~(0b00000001);//Disable Int0-Pin
87
88
while(1)
89
{
90
//start conditions for external interrupt (Wait until HREF is LOW to make sure to get a complete Line)
Derzeit stellt es sich wie folgt da:
Führe ich den Code wie oben dargestellt aus (und setzte einen Breakpoint
in der letzten If-Schleife, so zählt der Zähler nur bis eins, was für
mich absolut unverständlich ist.
Die interrupts kann ich nach wie vor durch Pin 13 nicht detektieren, was
mir ebenso nicht einleuchten will.
Kommentiere ich die letzte if-Schleife aus und pausiere willkürlich über
den Debug-Mode, haben beide Zähler den gleichen Wert. (Ich habe aber das
gefühl, dass sie zu langsam hochzählen)
Trotzdem sehe ich die ISR-Routine nicht auf dem Oszi.
von Michael kam folgender Beitrag:
>Ich wollte auch mehr darauf hinaus, daß es für das konrete Projekt nicht>wirklich etwas zwischen dem Einlesen von 2 Pixeln zu tun gibt.>Wenn man also eine Zeile komplett in einer HSync-ISR einliest und>zwischenspeichert, erspart man sich mögliche Timingprobleme mit einer>PCLK-ISR erstmal ganz.
Da stimme ich grob erstmal mit dir überein. Für mich stellt sich dann
aber die Frage, wie ich die PCLK-Flanken dann detektiere,
um dann jeweils das anliegende Byte zu übernehmen. Wie kann ich soetwas
denn abbilden? Die ISR wird doch nur einmal durchlaufen. Lasse mich da
gerne belehren :)
Auf den Beitrag von Igel1 bezogen:
>...>Und das Beste: so ein ARM-Prozessor kommt mit einem "Hardware->Debugger" daher - man kann seine Programme also Schritt für>Schritt debuggen - nicht im (buggy Atmel-)Simulator, sondern>nativ auf der Hardware (inkl. Register-Auslesen und Pi-Pa-Po)
über das Debug-Wire und dem Dragon kann ich doch auch die Hardware
direkt debuggen und auch die Register lesen inkl. Eingänge.
Oder liege ich da falsch?
Im Prinzip hast du vermutlich recht, dass dein Vorgeschlagener
Controller für diese Anwendung besser geeignet ist.
Ich habe mich aber damals für die Arduino (Atmel) Reihe entschieden und
auch bisher nur damit Erfahrungen gemacht.
Jetzt auf einen anderen Umzusteigen würde mich (zumindest für den
Anfang) wieder auf null zurückwerfen. Dafür fehlt mir leider noch etwas
die Zeit und die Motivation.
Mir ist bewusst, dass ich mit dem Atmega328 keine videos darstellen
werden kann.
Für mich geht es aber, wie Michael auch schon erkannt hat:
>Wozu also das Ganze? Man lernt Datenblätter zu lesen, man lernt I2C>kennen, man lernt es, das Zeitverhalten eines System in Hardwarenähe zu>beachten.>Das hilft aber auch auf anderen Systemen bei anderen Aufgaben.
Mir reicht es tatsächlich zunächst ersteinmal ein Foto zusammengesetzt
zu bekommen.
Das ich danach in Ruhe weiterverarbeiten kann. Ich habe in ferner
Zukunft damit dann vor, eine Art von Sortierer zu bauen. Wie gesagt,
ferne Zukunft :D
ab dem Sommer habe ich auch privat etwas mehr Zeit und dann kann man
sich den Schwenk auf einen ARM-Prozessor ja nochmal überlegen. :)
Dann noch der interessante letzte Beitrag von Igel1:
>Kurzum: Ein Polling-Mechanismus wäre vermutlich besser geeignet, um die>Pixel aus der Kamera in das RAM einzulesen.
Polling sagte mir bis zur Erstellung von diesem Beitrag noch nichts.
Sollte ich das eher mit einer While-Schleife oder If-Schleifen lösen?
(Mein verständnis von Polling ist "aktives" Warten, bin ich da richtig?)
Ich hoffe ihr könnt mir sagen, wo ich in obrigem Code einen Denkfehler
habe? Es ist ja nun wirklich noch keine hochkomplizierte Angelegenheit
und ich weiß einfach nicht wo das Problem liegt.
vielen Dank für eure Hilfe!
sonnige Grüße
David
Hi David. Erstmal Respekt für Deine Mühen und danke das Du deine
Gedanken mit uns teilst. Ich persönlicch finde es immer schwer mich in
den Code anderer Leute einzudenken, daher ist eine ausführliche
Dokumentation wichtig.
Von daher wäre mein Vorschlag bevor wir hier über Code diskutieren, den
Programmablauf zu beschreiben. Also was genau wie und warum erfolgen
soll. Darauf basierend kann dann jeder seinen Code schreiben, um zu
lernen und am Ende entwickeln wir einen gemeinsamen, z.B. in Github.
Ein guter Einstieg hierzu wäre, Deine Ideen zur Initialisierung in
Subroutinen zu gießen. Dazu müssten wir nur beschreiben was das System
vor Beginn und am Ende der Routine für einen Zustand hat und mit welchen
Kommandos wir dahin kommen.
Was hälst Du (sorry, ihr) von der Idee? Wollen wir so vorgehen?
Hallo,
David D. schrieb:> Da stimme ich grob erstmal mit dir überein. Für mich stellt sich dann> aber die Frage, wie ich die PCLK-Flanken dann detektiere,> um dann jeweils das anliegende Byte zu übernehmen. Wie kann ich soetwas> denn abbilden? Die ISR wird doch nur einmal durchlaufen. Lasse mich da> gerne belehren :)
soviel zu belehren ist da nicht. ;-)
Du nimmst die Länge einer Zeile in Bildpunkten und damit die Anzahl PCLK
die dazugehören. Dann rechnest Du Dir aus, wieviel zeit das in µs/ms
ist.
Dann ignorierst Du alle Überlegungen zur Länge einer ISR und machst
alles ab HSYNC innerhalb der ISR.
PCLK fragst Du simple per Loop ab, eben Pin einlesen und schauen, ob der
Pegelwechsel da war. Sonst eben in der Schleife weiter abfragen.
Wenn ja Daten holen, Pixelzähler weiterzeählen und wenn noch Pixeldaten
der Zeile fehle wieder ab in die Warteschleife auf PCLK.
Dann bist Du eben Zeit x in der ISR. Während der Zeit sind sowieso auf
dem AVR die Interrupts gesperrt und es kann Dich keiner stören.
So bekommst Du eine Zeile. Du bekommst ja vermutlich nichtmal eine Zeile
im Ram des AVR unter...
Ich schaue mir morgen mal das Datenblatt des OV7670 genauer an wie es
weiter gehen könnte.
Olli Z. schrieb:> Ein guter Einstieg hierzu wäre, Deine Ideen zur Initialisierung in> Subroutinen zu gießen. Dazu müssten wir nur beschreiben was das System> vor Beginn und am Ende der Routine für einen Zustand hat und mit welchen> Kommandos wir dahin kommen.
Selbstverständlich sollte sowas in Subroutinen/Funktionen ausgelagert
werden. InitCam() muß den kamerachip z.B. dann aus jeder Lebenslage in
einen von uns gewünschten Zustand setzen. Erstmal das notwendigste rein,
Register, die unbedingt auf gewünschte Werte gesetzt werden
sollen/müssen dann nachtragen wenn nötig ist.
Gruß aus Berlin
Michael
@David:
Ich programmiere, wie schon gesagt, ein paar Jährchen keinen AVR mehr,
daher muss ich nicht richtig liegen, aber Deine Art der PIN-Abfrage
scheint mir etwas seltsam:
Außerdem wäre es gut, wenn Du den gesamten Code hier
einstellst/anhängst.
So fehlt z.B. die Definition von OV_HREF_PIN in Deinem Code-Fragment.
Viele Grüße
Igel1
Hallo,
Andreas S. schrieb:> Außerdem wäre es gut, wenn Du den gesamten Code hier> einstellst/anhängst.
hatte ich auch schonmal drum gebeten, ich würde es dann eben auf einen
passenden AVR packen und mitschauen.
Ist bei mir reines Interesse. Wenn, dann hänge ich die OV7670 ohnehin an
einen ESP32. Die in Gang zubekommen dürfte mir kaum Probleme bereiten,
auch an einem Mega328 nicht. Die reale Möglichkeit habe ich ja schon vor
etlichen Jahren mit der DC3840 genutzt. Die hängt ja im Moment am ESp32,
siehe Posting vom 02.04.2018 13:42.
PS und OffTopic: heute 3 Stunden mit 2 Obi/Norma WLAN-Steckdosen
verbracht.
ESP8266 drin, 10 Leute haben das im Netz mit Tasmota u.ä. in Gang
gebracht, keiner hat ein wirklich sinnvolles wirklich Stück Doku
hinterlassen warum es einen IO für Relais on und einen IO für relais off
gibt. Steht zwar so auf der Platine, ist aber eigentlich etwas anders
gemeint.
Nun schalten sie wie sie sollen, hätte ich mir die ziemlich aufwändige
Beschaltung zwischen den ESP-Pins und dem Relais mal gleich selber
angeschaut... 3 Halbleiter (2 Transistoren, der dritte SOT-23 nicht
identifizierbar, könnte vom Drumrum soager ein thyristor o.ä. sein), ca.
10 Widerstande und Kondensatoren.
Ganz verstanden habe ich noch nicht, waum die Chinesen da soviel Aufwand
getrieben haben.
Gruß aus Berlin
Michael
David D. schrieb:> Der Verdacht des rekursiven Aufruf gefällt mir ganz gut.
Mir auch :-)
> Hatte aber auch> zu Beginn und zum Ende der Routine cli() bzw. sei() gesetzt, um diesen> Fall auszuschließen. Brachte aber leider keine Veränderung.
Hmmm - auch dafür müßten wir Deinen kompletten Code sehen.
> Hier mein Vollständiger Code (allerdings im AVR-Style)(Versuche das die> Tage mal auf Arduino umzumünzen, damit wir wieder auf der gleichen> Plattform sind)
Oh schreck - dann hängt Ihr mich vermutlich ab ...
> Ich hoffe, ihr könnt trotzdem etwas damit anfangen:
Ja, bloß bitte den vollständigen Code hier noch nachschieben.
> Trotzdem sehe ich die ISR-Routine nicht auf dem Oszi.
1
ISR(INT0_vect){
2
cli();
3
PORTB |= 0x20; //Just for measuring at oscilloscope
4
interruptFlag=true;
5
i++;
6
PORTB&= ~(0x20);
7
sei();
8
}
Vorab: "cli()" sollte meiner Meinung nach überflüssig sein,
weil beim Aufruf einer ISR das Globale Interrupt-Flag (I in SREG)
sowieso ausgeschaltet wird.
Gleiches gilt für "sei()" am Ende: Beim Rücksprung aus einer
ISR wird das globale Interrupt-Flag wieder aktiviert - das
gehört quasi zum Hotel-Service Deines MC.
Eine erneute steigende Flanke, die während einer "normalen" ISR
einläuft, wird also erst nach dem Rücksprung aus der ISR zum
neuen Interrupt führen.
Dieses (vermutlich von Dir gewünschte) Verhalten konterkarrierst
Du, indem Du sei() noch innerhalb Deiner ISR ausführst.
Das dürfte wiederum zu rekursiven ISR-Aufrufen führen.
Nun zurück zu Deiner ursprünglichen Frage/Aussage:
> Trotzdem sehe ich die ISR-Routine nicht auf dem Oszi.
Ich kontere mal und sage: trotzdem sehe ich nirgendwo, dass
Du PORTB überhaupt als Ausgang geschaltet hast ...
Viele Grüße
Igel1
David D. schrieb:>>Kurzum: Ein Polling-Mechanismus wäre vermutlich besser geeignet, um die>>Pixel aus der Kamera in das RAM einzulesen.> Polling sagte mir bis zur Erstellung von diesem Beitrag noch nichts.> Sollte ich das eher mit einer While-Schleife oder If-Schleifen lösen?> (Mein verständnis von Polling ist "aktives" Warten, bin ich da richtig?)
"Polling" heißt einfach: Frage aktiv Deinen PINx aus Deinem Programm
heraus immer wieder ab. Es ist das Konzeptionelle Gegenstück zu
Interrupts, die den Programmablauf "von sich aus" unterbrechen.
Nachteil von Polling: belastet den Prozessor, der dauernd fragen muss -
auch wenn gar kein Flankenwechsel passiert ist. Vorteil: Du sparst Dir
den Interrupt-Overhead.
> über das Debug-Wire und dem Dragon kann ich doch auch die Hardware> direkt debuggen und auch die Register lesen inkl. Eingänge.> Oder liege ich da falsch?
Nein, Du liegst da goldrichtig, nur ich kannte Debug-Wire nicht, weil's
scheinbar erst nach meiner AVR-Zeit aufkam. Schönes Feature!
> Im Prinzip hast du vermutlich recht, dass dein Vorgeschlagener> Controller für diese Anwendung besser geeignet ist.
Und Du hast ebenfalls recht, wenn Du Dich jetzt aktuell in kein
ARM-Abenteuer stürzen willst, wenn Du nicht viel Zeit hast.
Kann ich absolut nachvollziehen.
Viele Grüße
Igel1
Hallo,
ich habe zu makros auch eine geteilte Meinung.
Wenn man sie selbst geschrieben hat ok, wenn man sie übernimmt manchmal
riskant.
Prinzipiell ist es ja nur eine Textersetzung durch #define. Das kann in
Verbindung mit zusätzlichem kontext wie auch hier
if( bit_is_clear( OV_HREF_PIN, OV_HREF_PINNR) && (HREF_Flag==false))
Nebeneffekte erzeugen, weil nach ersetzen des Makro-Part die komplette
Auswertung ganz was anders machen kann als erwartet.
Wenn, dann würde ich da immer Funktionen vorziehen, die haben keine
solchen Nebenwirkungen.
Ich würde selbst hier
OV_HREF_PIN & (1 << OV_HREF_PINNR)
wohl (OV_HREF_PIN & (1 << OV_HREF_PINNR) == (1 << OV_HREF_PINNR))
schreiben, das liefert definitiv false oder true zurück.
Ob das Ergebnis ohne den Vergleich wirklich als true und false
interpretiert wird, kann schon vom Compiler abgängen. Die Diskussionen
dazu im Netz sind endlos...
Gruß aus Berlin
Michael
Das geht ja schon alles sehr tief in die Materie, alles hochspannend und
sehr informativ!
Ich sehe das wir schon noch auf unterschiedlichen Ebenen unterwegs sind
(Arduino, Atmega direkt, ESP, ARM). Persönlich würde ich auch die ohne
Overhead vorziehen, sprich AVR direkt, selbst wenn ein Arduino-Board
genutzt wird. Da muss man dann aber wirklich alles selbst machen, inkl.
SPI.
Wäre das denn ein „kleinster gemeinsamer Nenner?“ für unser
Gemeinschaftsprojekt?!
Ich glaube wir sind uns alle einige das wir mit dem Atmega328 sehr bald
an seine Leistungsgrenze stoßen werden. Dann darf man schonmal über
einen Nachfolger nachdenken. Da wird es in der AVR Liga schnell dünn.
Wenn wir also die Core-Logik übertragen wollen, sollten wir drauf achten
alle Prozessorspezifischen Aufrufe in Subroutinen auszulagern. Wenn wir
das gleich von Anfang an machen, könnten wir vielleicht alle hier
vertretenen Plattformen integrieren, als auch einen späteren Umstieg
erleichtern.
P.S.: Ein Github Repository würde ich hier, unterstützend zum Thread und
Wiki bereitstellen: https://github.com/igittigitt/ov7670
Schickt mir mal Eure Github-Accounts und ich trage die als Collaborators
ein, damit ihr das nach belieben nutzen könnt. Gleiches gilt fürs Wiki.
Ich hoffe das ist ok und ich nehm das hier keinem „weg“. Wenn doch,
bitte gleich schreien, nichts ist in Stein gemeißelt! :-)
Andreas, Deine Überlegungen zum ISR würde ich 100% teilen. Das Problem
sind die cli()/sei() Aufrufe innerhalb der Routine. Diese Befehle sind
für Programmcpde außerhalb von ISRs gedacht, die nicht durch einen
solchen unterbrochen werden sollen.
Viktor, ich stimme mit Dir überein, lesbarer Code ist die Basis für eine
sinnvolle Zusammenarbeit und erfolgreiches Debugging. Und lieber
Unterfunktionen anstelle Makros.
Sollen wir mal versuchen einen Programmablauf zu skizzieren und
Unterfunktionen zu nennen, die man dann mit Code füllen kann? Ich denke
mit diesem Gedankengerüst kommt man schneller zum Ziel, weil es uns
etwas „zusammenhält“.
@Victor:
Yep, Dein Makro sieht tatsächlich etwas schöner aus.
Gründe, die gegen so ein Makro sprechen, fallen mir ebenfalls nicht ein,
was nicht heißt, dass es eventuell doch welche gibt.
Ich selbst bevorzuge daher immer "mainstream coding style".
Ist halt etwas Geschmackssache.
@OV7670-Kämpfer:
Olli schlug vor:
> Sollen wir mal versuchen einen Programmablauf zu skizzieren und> Unterfunktionen zu nennen, die man dann mit Code füllen kann? Ich denke> mit diesem Gedankengerüst kommt man schneller zum Ziel, weil es uns> etwas „zusammenhält“.
Mit Blick auf die arg beschränkten AVR-Ressourcen, würde ich ein
Polling zum Einlesen einer beliebigen Zeile vorschlagen.
Und da das RAM des ATmega bereits nach dem Einlesen von nur
einer Zeile randvoll sein dürfte, würde ich nach dem Einlesen
der Zeile (evtl. sogar schon während des Einlesens), die
gelesenen Werte an den PC (oder an mein TFT-Display) versenden.
Erst wenn das erledigt ist, kann ich die nächste Zeile einlesen.
Dabei sollte mir bewußt sein, dass ich mich zu diesem Zeitpunkt
vermutlich schon X-Zeilen weiter im Frame befinde und daher die
nächste Zeile im folgenden Frame abpassen muß.
Der Ablauf wäre also:
Soweit mein Vorschlag.
Wie immer gilt: bitte nicht ohne genaues Nachprüfen übernehmen, denn
alles ist ungetestet und der Code ist ausschließlich aus den
TimingDiagrammen abgeleitet. Da ist bestimmt noch das eine oder
andere Schnitzerchen drin ...
Viele Grüße
Igel1
Michael U. schrieb:
> PS und OffTopic: heute 3 Stunden mit 2 Obi/Norma WLAN-Steckdosen> verbracht.
Auch wenn das wirklich voll Off-Topic war und wir hier nicht weiter
abschweifen sollten, so habe ich durch Deinen Hinweis erstmals erfahren,
dass es inzwischen alternative Firmware für Sonoff's gibt - das war
sehr interessant für mich. Danke für den Hinweis!
Viele Grüße
Igel1
Andreas S. schrieb:> Mit Blick auf die arg beschränkten AVR-Ressourcen, würde ich ein> Polling zum Einlesen einer beliebigen Zeile vorschlagen.
Das halte ich auch für eine gute Idee. Da wir im Moment nichts anderes
tun wollen als Daten von der Kamera zu lesen, gibt es eigentlich keinen
Grund sich der Komplexität einer ISR auszuliefern. Parallel zu dieser
würde unser Main-Code nämlich nur in einer Sinnlos-Schleife rotieren.
Ich glaub wir sollten erstmal versuchen das mit reinem Polling hin zu
bekommen.
Also die Main startet nach der Initialisierung mit einem Poll auf VSYNC
und dann gehts los.
Wir arbeiten doch mit QQVGA, also 160x120 Bildpunkten. Der XCLK wird mit
8 MHz gefahren und der PCLK schwingt sich somit auf 50 kHz ein. Das
macht eine Periodenzeit von 20µs, unser Bezugslevel.
Nehmen wir weiter an das wir die Bilddaten im RGB565 oder RGB555
Ausgabemodus übertragen. Ist etwas ineffektiver als YUV, aber erstmal
leichter zu verarbeiten. Jede Bildzeile hat also dann eine Länge von 320
Byte. Das gesamte Bild eine Größe von 38.400 Byte. Der SRAM des
Atmega328p ist 2.048 Byte groß, wovon ein guter Teil auch für das
Programm benötigt wird. Ich denke aber ein Zwischenpuffern von 2-3
Zeilen sollte schon drin sein.
Das Setup des OV7670 wäre dann doch so:
Du würdest also dadurch "Zeit schinden" indem Du einfach nur eine Zeile
pro Frame liest und überträgst? Ok, für den Anfang eine durchaus
brauchbare Methode. Da hat man vermutlich genug Zeit die Daten an den PC
zu bekommen.
> - Die erste Zeile eines Frames beginnt,> wenn VSYNC von Hi auf Low geht
Verstanden und bestätigt.
> - Die Zeile N beginnt,> wenn HREF genau zum N.ten mal von Low auf Hi geht
Verstanden und bestätigt.
Laut Timingtabelle ist das nach 17*PCLK, also 340us der Fall. Wir haben
also von der Erkennung der fallenden VSYNC-Flanke bis zur ersten Prüfung
auf eine steigende Flanke diese Zeit zur freien Verfügung. Ob das für
einen Kurzlurlaub reicht? ;-)
> - Die jeweiligen Pixel einer Zeile stehen bereit,> wenn PCLK von Low auf Hi geht
Verstanden und bestätigt, mit einer kleinen Anmerkung: Ich würde hier
nur nicht von Pixeln, sondern von Bytes sprechen. Denn wieviele Byte pro
Pixel benötigt werden, hängt vom Bildausgabeformat ab. In der Regel sind
es aber immer 2 Byte pro Pixel, da die Kamera keinen nativen
Graufstufenmodus kennt. Theoretisch könnte man den erreichen indem man
die Kamera auf YUV-Ausgabe stellt und immer nur das erste Byte
(Y=Luminanz) hernimmt und das zweite einfach ignoriert.
> - Die Zeile ist beendet,> wenn HREF auf Low geht
Verstanden und bestätigt. Das ist dann nach PCLK * H-Pixel der Fall.
Also 20us * 160 = 0,0032us = 3,2 ms. Anschließend folgt noch die
Austastlücke von 144 PCLK, also nochmal 0,00288us oder 2,88 ms. Dies
wäre für mich die Zeit die wir hätten um störungsfrei zum PC zu
übertragen.
>
1
>
> Soweit mein Vorschlag.
PERFEKT würde ich sagen, und von der Form her exakt das was wir
diskutieren sollten bevor auch nur eine einzige Zeile Code geschrieben
wird :-)
Ich bin begeistert! Gern würd ich das alles mal irgendwie im Wiki
ablegen, vielleicht auch mal mit Visio ein einfaches PAP dazu zeichnen.
Es sind ja die vielen kleinen Nebeninformationen zum Timing, etc. die
man später braucht, wenn man "mehr will".
Oli
Olli Z. schrieb:> Andreas S. schrieb:>> Mit Blick auf die arg beschränkten AVR-Ressourcen, würde ich ein>> Polling zum Einlesen einer beliebigen Zeile vorschlagen.> Das halte ich auch für eine gute Idee. Da wir im Moment nichts anderes> tun wollen als Daten von der Kamera zu lesen, gibt es eigentlich keinen> Grund sich der Komplexität einer ISR auszuliefern.
Ehrlich gesagt wäre der ISR-Ansatz der einfachere.
Aber damit kommt Ihr nicht weit, weil Aufruf und Rücksprung der ISR
halt viel Resourcen verbrauchen.
> Parallel zu dieser> würde unser Main-Code nämlich nur in einer Sinnlos-Schleife rotieren.> Ich glaub wir sollten erstmal versuchen das mit reinem Polling hin zu> bekommen.
Okay.
> Also die Main startet nach der Initialisierung mit einem Poll auf VSYNC> und dann gehts los.
Yep.
> Wir arbeiten doch mit QQVGA, also 160x120 Bildpunkten. Der XCLK wird mit> 8 MHz gefahren und der PCLK schwingt sich somit auf 50 kHz ein. Das> macht eine Periodenzeit von 20µs, unser Bezugslevel.
Legt Euch nicht von vorne herein auf QQVGA fest, sondern macht
den Code flexibel / konfigurierbar.
> Nehmen wir weiter an das wir die Bilddaten im RGB565 oder RGB555> Ausgabemodus übertragen. Ist etwas ineffektiver als YUV, aber erstmal> leichter zu verarbeiten.
Davon würde ich klar abraten.
Fangt erst einmal mit YUV an und verarbeitet zunächst nur das Y-Signal.
Das ergibt zwar nur SW-Bilder, aber das ist ideal, um überhaupt erst
einmal die Kamera einstellen zu können. Z.B. war ich lange Zeit der
Meinung, dass mein Programm nicht funktioniert und dabei war einfach
nur die Linse massiv unscharf eingestellt.
> Jede Bildzeile hat also dann eine Länge von 320> Byte. Das gesamte Bild eine Größe von 38.400 Byte. Der SRAM des> Atmega328p ist 2.048 Byte groß, wovon ein guter Teil auch für das> Programm benötigt wird. Ich denke aber ein Zwischenpuffern von 2-3> Zeilen sollte schon drin sein.
Claro, kann man gerne später dazuprogrammieren.
>> Das Setup des OV7670 wäre dann doch so:>>
1
> 1.) PCLK einstellen
2
> Prescaler-Register OV_SCCB_CLKRC (0x11) auf "Disable Double clock
> Register COM7 (0x12) mit Wert 0b0001 0100 laden.
7
> 3.) Skalierung einstellen
8
> Register COM3 (0x0C) mit Wert 0b0000 1000 laden.
9
>
Auch wenn's super wichtig ist - ich bin jetzt einfach mal zu faul,
das zu überprüfen ... Ich hoffe, ein anderer erbarmt sich.
Da man hier eine ganze Menge falsch machen kann, würde ich mit
einer Konfiguration beginnen, die nachweislich bei anderen Leuten
im Internet funktioniert hat.
>>>
1
>> N=0
2
>> while (N < Zeilenzahl_eines_Frames) {
3
>> Framebeginn abpassen
4
>> Alle Pixel der N.-ten Zeile einlesen
5
>> Alle Pixel der N.-ten Zeile ausgeben
6
>> N = N+1
7
>> }
8
>>
> Du würdest also dadurch "Zeit schinden" indem Du einfach nur eine Zeile> pro Frame liest und überträgst? Ok, für den Anfang eine durchaus> brauchbare Methode. Da hat man vermutlich genug Zeit die Daten an den PC> zu bekommen.
Richtig - das war der Grundgedanke.
Im nächsten Schritt läßt sich das natürlich deutlich verfeinern und
ist in Teilen im Pseudocode schon "vorgedacht":
Ihr könnt die max. Geschwindigkeit mit einer Art FiFo-Puffer erreichen:
vorne schreibt Ihr in den Puffer rein (so lange bis der Puffer voll ist)
und hinten nutzt holt Ihr die Bytes raus und übertragt sie an den PC
oder ein TFT-Display. Jedes übertragene Byte leert den FiFo-Puffer
dann wieder.
Sobald genug Platz für eine weitere Zeile ist, kann diese wieder
eingelesen und gespeichert werden, während hinten weiterhin die Bytes
entnommen und rausgeschrieben werden. Das Entnehmen und rausschreiben
kann in den oben markierten "Wunschcode"-Zeilen passieren.
>>> - Die erste Zeile eines Frames beginnt,>> wenn VSYNC von Hi auf Low geht> Verstanden und bestätigt.>>> - Die Zeile N beginnt,>> wenn HREF genau zum N.ten mal von Low auf Hi geht> Verstanden und bestätigt.> Laut Timingtabelle ist das nach 17*PCLK, also 340us der Fall. Wir haben> also von der Erkennung der fallenden VSYNC-Flanke bis zur ersten Prüfung> auf eine steigende Flanke diese Zeit zur freien Verfügung. Ob das für> einen Kurzlurlaub reicht? ;-)
Mindestens ;-)
Alternativ kann man in ca. 80us bei 115,2 kbit/s ein Byte übertragen.
>>> - Die jeweiligen Pixel einer Zeile stehen bereit,>> wenn PCLK von Low auf Hi geht> Verstanden und bestätigt, mit einer kleinen Anmerkung: Ich würde hier> nur nicht von Pixeln, sondern von Bytes sprechen. Denn wieviele Byte pro> Pixel benötigt werden, hängt vom Bildausgabeformat ab. In der Regel sind> es aber immer 2 Byte pro Pixel, da die Kamera keinen nativen> Graufstufenmodus kennt. Theoretisch könnte man den erreichen indem man> die Kamera auf YUV-Ausgabe stellt und immer nur das erste Byte> (Y=Luminanz) hernimmt und das zweite einfach ignoriert.
Genau damit würde ich an Eurer Stelle anfangen.
>>> - Die Zeile ist beendet,>> wenn HREF auf Low geht> Verstanden und bestätigt. Das ist dann nach PCLK * H-Pixel der Fall.> Also 20us * 160 = 0,0032us = 3,2 ms.
Nicht ganz: wie Du oben selber schreibt, benötigt man immer 2 Bytes
pro Pixel, also in Deinem Beispiel 6,2 ms für eine Zeile im YCrCb422-
Format.
> Anschließend folgt noch die> Austastlücke von 144 PCLK, also nochmal 0,00288us oder 2,88 ms. Dies> wäre für mich die Zeit die wir hätten um störungsfrei zum PC zu> übertragen.
... Könnte man meinen, aber leider bekommst Du bei 115,2kbit/s gerade
mal max. 36 Bytes in dieser Zeit per USART über die Leitung geschoben.
Die horizontale Austastlücke reicht also nicht zur Übertragung
der Zeileninformation.
Das wiederum bedeutet im obigen Pseudocode:
es wird auf den nächsten Frame gewartet und dort die nächste Zeile
entnommen. Will sagen: pro Zeile benötigt Ihr bei diesem Ansatz einen
Frame.
Mit der weiter oben von mir berechneten "Spaßgrenze" liegt Ihr bei
einer PCLK von 50kHz bei einer Framerate von 1 Frame / 16 Sekunden ...
(wenn die Kamera überhaupt so niedrige PCLK's erlaubt)
Um also 120 Zeilen zu übertragen braucht's hier 120 * 16s = 32 Minuten.
Das wird nicht spaßig werden.
Hmmm - ich glaube, vor dem Coding ist hier doch noch etwas
Konzept-Tuning nötig ... (wozu ich aber vermutlich heute und die
nächsten Tage nicht mehr kommen werde => Ihr seid dran ...)
>>>
1
>>
>> Soweit mein Vorschlag.> PERFEKT würde ich sagen, und von der Form her exakt das was wir> diskutieren sollten bevor auch nur eine einzige Zeile Code geschrieben> wird :-)>> Ich bin begeistert! Gern würd ich das alles mal irgendwie im Wiki> ablegen, vielleicht auch mal mit Visio ein einfaches PAP dazu zeichnen.> Es sind ja die vielen kleinen Nebeninformationen zum Timing, etc. die> man später braucht, wenn man "mehr will".>> Oli
Nur zu ...
Viele Grüße
Igel1
Hallo:
Olli schrieb:
>Von daher wäre mein Vorschlag bevor wir hier über Code diskutieren, den>Programmablauf zu beschreiben. Also was genau wie und warum erfolgen>soll. Darauf basierend kann dann jeder seinen Code schreiben, um zu>lernen und am Ende entwickeln wir einen gemeinsamen, z.B. in Github.
Ja. sehe ich genauso. (siehe meinen Post vom 28.03. 13:17)
Den hat aber jeder hier gekonnt ignoriert :D
Ich habe schon ein Github Projekt aufgesetzt und da drin zwischen
Arduino und AVR unterschieden, um den transfert auch besser
hinzubekommen.
Aber wir können auch gerne dein Repository nehmen. Wenn du dich damit
auskennst, ist es vielleicht sogar besser, wenn du die Adminstration
übernimmst, weil ich neu auf dieser Platform unterwegs bin.
Da denke ich auch, dass wir das Projektdashboard gut nutzen können, um
aufkommende Ideen festzuhalten.
>Ein guter Einstieg hierzu wäre, Deine Ideen zur Initialisierung in>Subroutinen zu gießen.
Ja sehe ich ebenfalls so. Ich nutze die Main-Funktion nur imme rzum
ausprobieren. Alles was sich dann als "richtig" erweist packe ich dann
in Routinen.
von Igel1:
>aber Deine Art der PIN-Abfrage>scheint mir etwas seltsam:
Jap... keine Ahnung was mich da geritten hat. Deine darstellung ist die
wohl gängigste, an die wir uns auch halten sollten.
Werde ich sofort ändern. (Nichtsdestotrotz sollte meine auch
funktionieren. Daher scheint das für mich nicht die Ursache des Problems
zu sein)
>Außerdem wäre es gut, wenn Du den gesamten Code hier>einstellst/anhängst.
Jap. die werden in der OV7670_init initialisiert. Ich wollte hier nicht
den Thread damit sprengen.
Ich denke wir werden das dann jetzt über GitHub realisieren, was das
ganze übersichlticher machen sollte.
@Michael
>hatte ich auch schonmal drum gebeten
Ebenfalls richtig. Tut mir leid hatte ich vergessen. Aber da auf meinen
Post mit dem Github keiner geantwortet hat war mir auch nicht klar, ob
das noch gewünscht ist.
@Igel1
>Dieses (vermutlich von Dir gewünschte) Verhalten konterkarrierst>Du, indem Du sei() noch innerhalb Deiner ISR ausführst.>Das dürfte wiederum zu rekursiven ISR-Aufrufen führen.>Nun zurück zu Deiner ursprünglichen Frage/Aussage:>> Trotzdem sehe ich die ISR-Routine nicht auf dem Oszi.>Ich kontere mal und sage: trotzdem sehe ich nirgendwo, dass>Du PORTB überhaupt als Ausgang geschaltet hast ...
Rekursiv heißt doch, dass die Funktion aus der Funktion selber
nocheinmal aufgerufen wird.
Also in dem Beispiel wäre es ja quasi nur indirekt, wenn aus der ISR
nochmal in die ISR gesprungen wird.
Das scheint aber ja dann nicht zu gehen, wenn die Interrupts erst beim
Rausspringen aus der ISR freigegeben werden.
Was ist dann nach deinem Verständnis ein Rekursiver aufruf?
Die initialisiserung des PORTB wird wie schon erwähnt ebenfalls in der
OV7670_init ausgeführt.
Richitg, dass könnt ihr nicht sehen aber ich habe es schon mehrfach
überprüft.
Wird dann sicherlich auch in GitHub als ganzes nachvollziehbar sein.
@Michael:
>Ich würde selbst hier>OV_HREF_PIN & (1 << OV_HREF_PINNR)>wohl (OV_HREF_PIN & (1 << OV_HREF_PINNR) == (1 << OV_HREF_PINNR))>schreiben, das liefert definitiv false oder true zurück.
Das finde ich bisher noch am besten.
Wow ist ja eine Menge zusammengekommen diese Woche.
die letzen Posts mit dem Polling muss ich nochmal überdenken und sacken
lassen. Für die ersten "Shots" sicherlich machbar.
Zu dem Verfahren mit dem Debug-Wire mache ich morgen ein kleines
Tutorial (Habe ich zurzeit aber nur am UNO zum laufen gebracht, weil es
erheblich drauf ankommt, wie die Schaltungstechnische Anbindung der
Reset Leitung ist.
mehr Dazu morgen (bzw. heute).
lg. und danke für die rege Unterstützung.
David
Hier der versprochene Post zum Debug-Wire:
Benötigt:
Hardware:
Arduino UNO, AVR-Dragon
Software IDE:
Atmel-Studio
Der Atmega328P unterstützt das besagte Debug-Wire. Dazu wird mittels des
AVR-Dragon (oder einem anderen Programmer) der/die/das Fuse DWEN mittels
ISP Programmierung gesetzt. Vorsicht! Hier besteht jetzt die Gefahr sich
auszusperren (wie mir erst kürzlich passiert). Das Debug-Wire
funktioniert nämlich nur, wenn die Reset-Leitung vollkommen frei ist.
Sprich wenn ich die Fuse gesetzt habe und Debug-Wire nicht funktioniert
komme ich nicht mehr zurück in den ISP-Modus und muss mit HighVoltage
Programmierung die Fuse wieder entfernen.
Beim Arduino UNO ist oben auf der Platine eine Kontaktbrücke vorgesehen.
(Bei mir auf dem SaintSmart Board steht dort Reset ON. Diese brücke kann
man einfach mit einem kleinen Schraubenzieher wegkratzen. Dann
funktioniert mit dem UNO das DebugWire problemlos. Bei dem Nano geht das
nicht ohne weiteres.
hier habe ich eine wie ich finde ausführlich und gut beschriebene
Anleitung gefunden:
http://www.hilltop-cottage.info/blogs/adam/debugging-arduino-using-debugwire-atmel-studio-and-an-avr-dragon/
Falls danach noch weitere Fragen auftreten sollten einfach melden :)
Hallo,
ich bin ja wegen des Thread-Titels hier reingeraten weil ich mir mal
eine OV7670 mitbestellt hatte und damit rumspielen wollte.
Inzwischen ist mir aber völlig unklar, wohin dieser Thread eigentlich
ziehlt.
Die Absicht, mit der Kamera an einem Mega328 irgendwie irgendein Bild zu
bekommen und irgendwie anzuzeigen/zum PC zu übertragen/zu speichern,
scheint ja völlig unwichtig zu sein.
Die Diskussionen über Programmierstile, StyleGuides, Programmstrukture
usw. scheinen ja Vorrang zu haben.
Ich habe damit kein Problem, es ist aber nicht der Grund meines
Interesses.
Ich werde weiter mitlesen, sehe aber im Moment den Sinn der ganzen Übung
nicht.
Ich bin eigentlich der Typ, der gern das macht, was nicht geht. ;)
Dazu muß das aber (für mich) irgendeinen Sinn und Zweck haben. Ein
brauchbares "Foto" einer kleinen Kamera mit dem Mega328 zu erstellen,
irgendwie zu übertragen und dann eben anzeigen wäre ein Zweck.
Das ist aber mit der OV7670 so nicht machbar. Referenz wäre für mich
immernoch mein Posting zur alten DC3840. Also 640x480 in Farbe als
Snapshot mit Übertragungszeit um 10-15s. Das hat der Mega32 vor Jahren
als Webserver hinbekommen. Die OV7670 bietet dazu aber von ihren
technischen Voraussetzungen keine Möglichkeit. Dazu wäre externer Ram
nötig, am Mega328 eben SPI-Ram mit mehr als 256kB oder die OV7670 mit
FIFO drauf.
Ich habe vorhin beim Googeln diesen link gefunden:
http://www.instructables.com/id/OV7670-Arduino-Camera-Sensor-Module-Framecapture-T/
Ich habe spaßhalber mal auf einen Arduino Nano gepackt und sein
Javaprogramm installiert, extra noch ein 32Bit Jave installiert.
Es läuft soweit, er liest ein 320x240 in s/w aus und schikct es mit
500kBaud direkt zum PC. Auf dem PC wartet seine Java-Software af einen
Bildanfang, klebt den passenden BMP-Header dazu und speichert es in
einen Ordner. Es kommt ca. alle 2-3s ein Bild an. Qualität war
unbrauchbar, erkennbar, aber Streifen usw. Da gibt es aber einen langen
Thread bei arduino.cc zu:
https://forum.arduino.cc/index.php?topic=159557.0
Ich habe hier jetzt nur gepostet, weil es ja ursprünglich mal um die
Kamera am Mega328 ging...
Ich wünsche den Beteiligten natürlich weiterhin viel Erfolg.
Gruß aus berlin
Michael
Hallo,
zu DebugWire:
David D. schrieb:> Beim Arduino UNO ist oben auf der Platine eine Kontaktbrücke vorgesehen.> (Bei mir auf dem SaintSmart Board steht dort Reset ON. Diese brücke kann> man einfach mit einem kleinen Schraubenzieher wegkratzen. Dann> funktioniert mit dem UNO das DebugWire problemlos. Bei dem Nano geht das> nicht ohne weiteres.
warum sollte ich DebugWire in dieser Kombination benutzen wollen? Weil
es DebugWire gibt?
Wenn man den UNO wieder automatisch aus der IDE programmieren will muß
der 100nF aber wieder ran. Beim Nano muß man ihne halt selber suchen
(bei meinem unter neben dem Elko am Spannungsregler). Bei meiner
Nano-Version ist auch der PullUp am Reset mit 1k bestückt statt mit 10k
wie im Schaltplan. Kann sein, daß man den auch noch tauschen müßte.
In der ArduinoIDE kann man auch die Serielle gut genug zum Debug nutzen,
früher kam bei mir auf die kleinen AVR eben ein SoftUART rauf, der
konnte nur Ausgaben über einen PIN als TX.
Ein Controller würfelt nicht, der macht genau was man ihm gesagt hat,
auch wenn es nicht unbedingt das ist, was man sagen wollte und erwartet.
;)
Egal ob DebugWire oder Debugausgaben über einen UART: in jedem Fall
verändert man an der Stelle das Timing bis zum Stillstand und kann
Abhängigkeiten mit externer Hardware kaum sinnvoll erfassen weil die
davon nichts weiß...
Gruß aus Berlin
Michael
Hallo Michael,
der Exkurs zum Debugwire kam nur auf Anfrage von Olli und soll in diesem
Thread hier auch nicht weiter thematisiert werden. Mir hat er bis jetzt
geholfen, den ein oder anderen Fehler im Code zu identifizieren. Das das
über eine mögliche Seirielle-Debug Funktionen von der Arduino-IDE aus
möglich ist mag richtig sein. Damit habe ich noch keine Erfahrungen
gemacht.
Zum thematischen ausufern gebe ich dir recht. Hier werden soviele
Informationen zuzsammen getragen, dass es schwer wird, das ganze
beisammen zuhalten. Daher hoffe ich auf Olli und sein Github repository
damit wir da einen gemeinsamen Code-Überblick generieren können und uns
in diesem Thread wieder auf die tatsächlichen Fortschritte konzentrieren
können und die kleineren Code-Diskussionen ins GitHub verlagern.
Ich hoffe nicht, dass du das Interesse verlierst, auch wenn es an der
ein oder anderen Stelle einmal ausufert :)
um das klar zu stellen:
Ziel ist es mit dem OV7670 und dem Atmega328 und im ersten Schritt einem
PC ein Bild zu erzeugen. Selbst wenn wir auf eine Framerate von 1/min
kommen :D Hauptsache ein Bild.
Danach setzen wir uns ein neues Ziel
liebe Grüße
David
Hallo,
David D. schrieb:> Ziel ist es mit dem OV7670 und dem Atmega328 und im ersten Schritt einem> PC ein Bild zu erzeugen. Selbst wenn wir auf eine Framerate von 1/min> kommen :D Hauptsache ein Bild.> Danach setzen wir uns ein neues Ziel
gut. Mein Problem zur zeit ist: die OV7670 scheint keinen Snapshot-Mode
zu können. Also ein Bild "belichten" und dann genau dieses Bild aus dem
Kameraspeicher identisch so oft auszulesen wie man möchte.
Sie scheint generell mit den eingestellten Werten zu grabben und dann
eben das Bild abzuliefern. Damit wäre beim nächsten auuslesen der
kameradaten das Bild nicht identisch mit dem vorhergehenden weil sich
entweder im Bild was bewegt hat oder weil die Toleranzen des Sensors
immer geringfügig abweichende Pixeldaten erzeugen. Damit wäre
stückweises übertragen eines Bildes an den PC nicht ohne
Bildfehler/Streifen/Doppelkonturen möglich.
Die Daten eines Bildes im Stück mit dem kleinen AVR zu übertragen ist
möglich (siehe mein Link dazu) mit 500kBaud, vermutlich auch mit 1MBaud.
Da hat aber der AVR nur die Aufgabe die Daten der Kamera zu lesen und
dem UART in die Hand zu dreüken. Es erfordert also auf dem PC eine
spezielle Software, die die ankommenden Rohdaten in ein nutzbares Format
packt.
Das macht oben im Link sein Java-Tool. Das ist aber für mich keine
Option die einen wirklichen Nutzen hat. Ich sehe in der Kombi OV7670 und
Mega328 im Moment keinen wenigstens theoretich realisierbaren Weg.
Damit lande ich zumindest dabei, daß ich mit dieser Kamera am ESP32
weiterspiele. Da reicht sowohl der Ram um ein komplettes Bild einzulesen
und die Rechenleistung um es dann per Webserver o.ä. zu übertragen.
Auch da kommen nur wenige Bilder/s raus, hier ist es aber die
Kombination aus Kosten für OV7670 und ESP32. Damit kann ich "rumspielen"
und für mich optimieren.
Reicht dann sicher z.B. als WLAN-Wettercam auf dem Balkon. Hat dann 10€
gekostet und ich habe vollen Zugriff auf die Software.
Für eine "richtige" Anwendung könnte ich einen raspi Zero W + seiner Cam
nehmen. Sind dann eben 30€ und ein paar Skriptgeschichten. Brauche ich
aber nicht...
Gruß aus Berlin
Michael
Hallo,
> Es erfordert also auf dem PC eine>spezielle Software, die die ankommenden Rohdaten in ein nutzbares Format>packt.>Das macht oben im Link sein Java-Tool. Das ist aber für mich keine>Option die einen wirklichen Nutzen hat. Ich sehe in der Kombi OV7670 und>Mega328 im Moment keinen wenigstens theoretisch realisierbaren Weg.
wie von mir vor den Osterfeiertagen versprochen hatte ich mich da auch
schon an ein Tool für den PC gemacht, dass die Empfangenen Daten in ein
Bild umwandeln soll. Da bin ich auch schon gut vorwärts gekommen. Da
warte ich jetzt nur noch darauf, dass wir uns für ein
"Übertragungsprotokoll" einigen, damit ich das dann auch Verwende. Löst
die angesprochene Speicherkapazität nicht. Aber für einen ersten Shot
würde ich mich auch mit Bildfehlern oder Doppelkonturen zufrieden geben.
liebe Grüße
David
Hallo,
David D. schrieb:> wie von mir vor den Osterfeiertagen versprochen hatte ich mich da auch> schon an ein Tool für den PC gemacht, dass die Empfangenen Daten in ein> Bild umwandeln soll. Da bin ich auch schon gut vorwärts gekommen. Da> warte ich jetzt nur noch darauf, dass wir uns für ein> "Übertragungsprotokoll" einigen, damit ich das dann auch Verwende. Löst> die angesprochene Speicherkapazität nicht. Aber für einen ersten Shot> würde ich mich auch mit Bildfehlern oder Doppelkonturen zufrieden geben.
und warum nicht "erstmal testen"? Ein festes Startzeichen asu wenigen
Buchstaben und dann die Daten der Kamera hinterher. ComputerNerd hat RDY
genommen. ;)
Die Anzahl Bytes pro zeile und die Anzahl Zeilen pro Bild stehen ja
ohnehin mit dem Setzen der Cam auf eine Auflösung und ein Format fest,
man kann also die ankommenden Bytes einfach mitzählen.
Da ich bei meinem LogicAnalyer vor Jahren die Daten des externen 32k Ram
am AVR auch so übertragen habe weiß ich, daß es prinzipiell kein Problem
mit 500000 Baud und den gängigen USB-Wandlern gibt. Auch FTDI, CP2102
und CH340 können die auf den Arduinos.
Das Startzeichen sollte nur so sein, daß es in den Daten nicht oder nur
sehr selten vorkommt, sonst bekommt der Empfänger Prpbleme den nächsten
Bildanfang sicher zu erkennen. Klappt praktisch aber mit seinem RDY
problemlos.
Die Beschaäftigung, die Kameraregister so zu setzen, daß möglichst ein
erkennbares Bild dabei rauskommt, bleibt ohnehin. Normalerweise findet
man dazu Application-Hinweise des Herstellers oder eben Beispiel von
Leuten, die es schonmal geschafft haben.
Das kann etwas an Zeit kosten.
Die Senderoutime auf dem AVR ähnelt meiner damaligen weil sie eben nur
aus Warten auf VSYNC, warten auf HSYNC und dann bei jedem PCLK Byte8s)
holen und in den UART packen.
Das ist Beschäftigung für einen Nachmittag bis es prinzipiell läuft und
Zeit für das Debug auf PC-Seite. Das hat mich damals einige Zeit
gekosten (noch in VB6), weil die COM durchaus nicht meiner Meinung war
was Empfangsbuffergröße usw. anging...
Gruß aus Berlin
Michael
David D. schrieb:> Trotzdem sehe ich die ISR-Routine nicht auf dem Oszi.
Kleine Bitte:
Könntest Du, David, den o.g. Code hier einmal vollständig als Anhang
einstellen? Zumindest so lang, bis Olli GitHub am Laufen hat?
Ich verstehe nämlich nach wie vor nicht, warum Dein Oszi nichts anzeigt.
Hast Du die von mir vorgeschlagenen Codeänderungen einmal ausprobiert?
Viele Grüße
Andreas
Hallo Andreas,
wie gewünscht der Code. Ich habe gerade deine Code-Änderungen noch
eingefügt und getestet (Also die mit der Bit-Abfrage, nicht das Polling)
leider keine Änderungen.
Im Anhang ist das ganze Projekt.
interessieren muss dich aber nur die main, OV7670 und evtl. die Uart,
wobei die da eigentlich nicht mitmischen sollte.
lg.
David
Hallo,
ich habe mir gerade mal den Spaß gemacht das Archiv zu entpacken und die
nötigen Dateien in die ArduinoIDE zu werfen.
Compiler läuft durch, der Nano meldet sich.
unschön: ich habe auf die Schnelle keinen Hinweis oder Kommentar
gefunden, der mir die aktuell eingestellte Bausrate ohne Suchen verraten
hätte.
Der Kommentar in der UART.cpp bei UBRR0L ist recht witzlos weil ich da
erst einen umrechnen muß und die Bits dazu raussuchen...
ok, sind 38400, der Nano meldet sich.
Fehler beim Versuch mit der Kamera zu reden?
Oh, TWI sind nur Dummys...
In OV7670.c geschaut.
void OV_SCCB_Init (void)
Nanu? Da werden I2C-Clock und I2C-Data hart auf Ausgang und H gesetzt???
I2C/TWI darf NIE einen festen H-Pegel auf den Leitungen haben, der Slave
darf diese JEDERZEIT auf aktiv L ziehen und das ist dann unlustig für
die Treiber der Beteiligten! I2C muß IMMER ein openDrain-Ausgang sein.
Ich habe hier erstmal abgebrochen, AVR und vermutlich auch die Kamera
sind im Allgemeinen zwar "hart im Nehmen", aber quälen muß ich die Clock
und Data-Leitungen nun auch nicht unbedingt...
Ich vermisse auch eine Komentarübersicht, welche Pins der Kamera auf
welchen Portpins sind. Ein Vergleichen der Anschlüsse ist so mehr als
mühsam. Als Liste brauchte ich nur rüberzugehen um zu sehen, daß ich
vielleicht HSYNC auf einem anderen Pin habe und dann entweder
umzustecken oder genau diese eine Zuordnung in der OV7670.h zu ändern.
Gruß aus Berlin
Michael
Hallo Michael,
>Nanu? Da werden I2C-Clock und I2C-Data hart auf Ausgang und H gesetzt???>I2C/TWI darf NIE einen festen H-Pegel auf den Leitungen haben, der Slave>darf diese JEDERZEIT auf aktiv L ziehen und das ist dann unlustig für>die Treiber der Beteiligten! I2C muß IMMER ein openDrain-Ausgang sein.
Das scheine ich dann immernoch nicht verstanden zu haben... das mit dem
openDrain. Da muss ich wohl nochmal in die Lektüre.
Kommentare sind es definitiv zu wenig, da gebe ich dir ohne weiteres
recht. der Code war auch (noch) nicht für die Öffentlichkeit bestimmt.
lg.
David
PS: die Anschlüsse müssten aber so wie viel weiter oben mit Olli
festgelegt, sein. (nur Pin 13 und evtl. die PCLK liegen an einem
anderen)
Hallo,
David D. schrieb:> Kommentare sind es definitiv zu wenig, da gebe ich dir ohne weiteres> recht. der Code war auch (noch) nicht für die Öffentlichkeit bestimmt.
das ist eine Fehleinschätzung. Kommentare müssen erstmal helfen, den
eigenen Kram jederzeit zu verstehen. "Jederzeit" heißt auch, wenn man es
aus 5 Jahren mal wieder anfasst.
Ich habe es mir zur Gewohnheit gemacht, in Stichpunkten sofort zu
kommentieren wenn eine Funktion o.ä. erstmal irgendwie läuft.
Solche Sachen fäßt man nur selten nochmal an und dann bleiben sie
unkommentiert.
>> PS: die Anschlüsse müssten aber so wie viel weiter oben mit Olli> festgelegt, sein. (nur Pin 13 und evtl. die PCLK liegen an einem> anderen)
Wenn es sich jetzt ergibt, daß jemand, so wie ich jetzt, mal mittesten
will oder in den Code schauen will, muß er mit dem Archiv klarkommen,
wie es ist.
Ich nehme also den Mega328, die Kamera und will es mal schnell zusammen
bauen. Ich lade mir oft Sourcearchive aus dem Internet wenn jemand eine
Komponente nutzt, mit der ich gerade rumbastel. Wenn das aus irgendeinen
Forum stammt, sieht es (leider) öfter ähnlich Deinem aus.
PS: das sollen alles nur Hinweise und Vorschläge sein und vielleicht
auch ein wenig (20 jahre?) Hobby-Erfahrung dazu und die Erkenntnis, daß
ich alte AVR-ASM-Sourcen von vor einigen Jahren auch nur mit Mühe wieder
verstehe weil zuwenig oder die falschen Sachen kommentiert...
Als trost für Dich: meine ASM-Source von 2000 macht I2C auf einem
90S8515 (Vorgänger des Mega8515) macht auch genau das falsch und spielte
trotzdem.
Zumindest zusammen mit dem benutzten I2C-Slave (MAS3507D)...
Gruß aus Berlin
Michael
David D. schrieb:> Hallo Michael,>>>Nanu? Da werden I2C-Clock und I2C-Data hart auf Ausgang und H gesetzt???>>I2C/TWI darf NIE einen festen H-Pegel auf den Leitungen haben, der Slave>>darf diese JEDERZEIT auf aktiv L ziehen und das ist dann unlustig für>>die Treiber der Beteiligten! I2C muß IMMER ein openDrain-Ausgang sein.>> Das scheine ich dann immernoch nicht verstanden zu haben... das mit dem> openDrain. Da muss ich wohl nochmal in die Lektüre.
Hier schön kurz und einfach erklärt (mit Schalter-Analogie):
Beitrag "Re: Open-Drain/Open-Source-Verständnis"
Oder hier ganz ausführlich:
https://www.elektronik-kompendium.de/sites/slt/1206121.htm
Oder natürlich Wikipedia:
https://de.wikipedia.org/wiki/Open-Collector-Ausgang>> Kommentare sind es definitiv zu wenig, da gebe ich dir ohne weiteres> recht. der Code war auch (noch) nicht für die Öffentlichkeit bestimmt.
Es wäre jetzt etwas gemein, wenn ich zunächst laut nach dem Code
schreie, Du ihn widerwillig rausgibst (weil Du weißt, dass er noch
nicht allgemeinverständlich dokumentiert ist) und ich mich
anschließend über die schlechte Dokulage beklage ...
Ich sitze daher mit zusammengepressten Lippen auf meinem Stühlchen :-)
Allgemein stimme ich Michael zu: was man nicht sofort dokumentiert,
wird meist nie dokumentiert. Und was nicht dokumentiert ist, das
durchschaust Du bereits nach wenigen Wochen (bei mir: nach wenigen
Tagen) nicht mehr.
Im gleichen Atemzug muss ich allerdings auch zugeben, dass mein
persönlicher, innerer Doku-Schweinehund mir auch so manchen Streich
spielt und ich daher Null Legitimation habe, den mahnenden Zeigefinger
zu heben ...
> PS: die Anschlüsse müssten aber so wie viel weiter oben mit Olli> festgelegt, sein. (nur Pin 13 und evtl. die PCLK liegen an einem> anderen)
Es wäre sehr nett, wenn Du die exakte PIN-Belegung/Verschaltung bitte
noch nachreichen könntest. Für Dich ist das sicherlich ein Klacks, für
einen
hilflosen Code-Reviewer ist Re-Engineering von PIN-Belegungen immer eine
Strafarbeit ...
Ach ja: und schreibe bitte nochmals, welches Board (Arduino Nano?) und
welche IDE (Atmel Studio, in welcher Version?) Du benutzt.
Viele Grüße
Igel1
Huhu,
Ja... ihr habt ja recht :D ich gelobe Besserung.
Das mit der nachträglichen einfügen der Kommentare habe ich auch bei mir
schon festgestellt, dass ich es nicht immer beibehalte...
Atmelstudio 7 (Version 7.0.1417)
zur xCLK Erzeugung nutze ich einen Arduino Nano an dem ich die CLK Out
fuse gesetzt habe und daher an D8 ca. 16Mhz anliegen. (controller2 im
Schaltplan)
ansonsten nutze ich für den Controller1 das Arduino UNO Board
(abweichend vom Schaltplan), dass aber ja die gleichen Pins (zumindest
die von mir genutzten) nach außen geführt hat wie der Nano. (der Grund
ist einfach die Debugging Möglichkeit, mit der ich nur Erfahrungen auf
dem UNO habe)
Allerdings sollte das Board einfach austauschbar sein.
lg.
David
Ps. Danke für die Links, die werde ich mir heute Abend direkt anschauen
:)
Michael, in einigen Posts zuvor hast Du noch gemeint das wir uns zuviel
um Konventionen scheren, als zu coden... und jetzt wird klar als
unfertig, unoffziell, gehackter Code diskutiert. Hmmm... so ganz komm
ich da jetzt nicht mehr mit.
Lasst uns doch kurz die Konventionen zuende bringen und gut. Dazu gehört
neben einem Schaltplan, den bisherigen Erkenntnissen, natürlich auch ein
Definitions-file und selbstverständlich auch sinnvolle Kommentarierung.
Zum Schaltplan:
Ich hatte auch schonmal einen in Eagle begonnen. Musste mir dafür ein
OV7670 Item anlegen, weil ich keins fand. Grundsätzlich gehört der Plan
im Quellformat, als PDF und Bild ins Reprository.
Zur Takterzeugung:
Einen zweiten Arduino würde ich nicht nehmen für den Takt, außer es
besteht hier jemand auf 16 MHZ und nicht den 8 MHZ, die man auch ganz
ohne Fuse-Tricks erzeugen kann. Hier würde ich den Hinweis mit dem CTC
anstelle PWM nochmal aufgreifen. Für 16 MHz sind wir später beim lesen
mit dem Mega328 eh viiel zu langsam, also wozu der Stress ;-)
Zur Plattform:
Ich glaube die Puristen sind hier in der Mehrzahl, also würde ich mich
dem anpassen und „reinen“ AVR-Code programmieren, ganz unabhängig von
Arduino Libs.
Zum I2C:
Die Arduino Lib „Wire“ berücksichtigt alles genannte (Open Drain, etc.).
Da wir aber ohne auskommen wollen, könnte man sich eine entsprechende
Lib für reinen AVR code suchen, oder die Lib portieren. Das wäre was
fürs Repo :-)
Apropos Repo:
Das Projekt ist öffentlich und jeder darf ziehen:
https://github.com/igittigitt/ov7670
NOCH steht nix drin. Ich werde aber das was hier als Konvention
rauskommt dort hinterlegen (z.b. in der Readme oder als Wikiseite).
Ich fang, wenns recht ist, einfach mal damit an eine Struktur zu
erstellen und die wichtigen Links zu sortieren.
So und jetzt bitte schnell einigen und ran an den Speck! Ich will auch
mal bald ein Bild sehen ;-)))
Oli...
Diese sollte den Code
Hallo,
Andreas S. schrieb:> Ich sitze daher mit zusammengepressten Lippen auf meinem Stühlchen :-)
:-)))
naja, ich bin auch alles andere als Vollkommen in der Beziehung, habe
mir eben genau deshalb recht früh einen eigenen Rahmen gesteckt und
halte mich daran. Meist... Oft...
Andreas S. schrieb:> Ach ja: und schreibe bitte nochmals, welches Board (Arduino Nano?) und> welche IDE (Atmel Studio, in welcher Version?) Du benutzt.
Ich habe seinen Ordner OV7670_Kamera in meinen Sketchordner der
ArduinoIDE gekippt, nur die main.c in OV7670_Kamera.ino umbenannt. Den
Nano eingestellt und compiliert und aus der IDE geflasht. Lief
problemlos durch und meldete sich. Eigentlich aber nur, weil er mit
#include "OV7670.c die Datei in main.c includioert hat. Ist eigentlich
falsch, nur die .h wird includiert, die .c werden ja normalerweise
einzeln vom Compiler bearbeitet und dann nur die Objekt-Files Files vom
Linker zusammengeknotet.
Ich wollte erst ein AVR-Studio 4 Projekt draus machen, das liegt hier
noch startbereit, allerdings irritierten mich die .cpp Files.
Wie kommt eigentlich die Namengebeung zustande? Ich habe auf den ersten
Blick in den .cpp Files nichts C++ typisches gesehen, ist doch reines C?
Gruß aus Berlin
Michael
Ursprünglich wollte ich da mit Objektorientierung ran... aber das gab
dann Probleme beim kompilieren, bzw. einfach schon nur bei der
Verwendung von .cpp files. Warum die main jetzt noch ein .cpp file ist
und warum es trotzdem Funktioniert kann ich grade nicht mehr beurteilen.
... Ich bereue es immer mehr das Projekt hochgeladen zu haben :D :D :D
... nein.. immerhin lerne ich dadurch, dass mir andere meine Fehler
aufzeigen.
das mit dem include des c-Files nicht richtig ist, wieso das noch dadrin
steht weiß ich grade auch nicht mehr.... hust hätte ich das mal besser
kommentiert hust
war vermutlich nur ein Test weil er die Header Datei nicht erkannt hat
oder sonst was... Das hat mir - auch wenn es falsch ist - über
Fehlermeldungen hinweggeholfen, an denen man aber sicher nochmal
ansetzten müsste
@ olli
sehr gerne, ich brenne auch schon förmlich. Es freut mich das du mit auf
die Amtel Ebene kommst :)
liebe Grüße
David
Michael, wie wärs wenn Du uns mal ein sauberes GERÜST zusammenstellst.
Verzeichnisstruktur und leere Files. Gern auch schon das .h File mit den
defines oder zumindest der Idee davon um die ganzen Parameter zu setzen.
Ich plag mich in der Zwischenzeit mit der Installation von AVR Studio 7
rum...
Hallo,
da sind sie wieder, meine 3 Probleme... ;)
Ich kann es mal nach meiner Ansicht versuchen. "meine Ansicht" deshalb,
weil:
ich kann weder C noch C++ wirklich. Grundlagen habe ich mir
projektabhängig über die letzten Jahre zusammengesucht, C++
bekanntschaft erst durch die Arduino-Geschichte.
Es war und ist nur Hobby, vom Z80 über 6510 zu den ersten AVR usw. Alles
in Assembler. C kam als Notwendigkeit weil mein Anfang einen TCP-Stack
in ASM zu schreiben zwar durchaus gangbar war (IP ging, TCP ging, ARP
ging ICMP-Ping ging grundsätzlich. Alles nur, weil der ENC28J60 Ethernet
Chip bezahlbar beschaffbar war und LAN am AVR.. Super!
Dann kam U.Radig mit seinem Webserver daher und ich stand vor der
Entscheidung, meins weitermachen oder mich in C einzulesen und seine
Software an meine Wünsche anzupassen. Ich habe mich für seine Software
entschieden...
Entscheidend dafür war, daß ich auf Grund meiner eigenen Basteile TCP/IP
usw. ausreichend verstand, um recht zielsicher die C-Funktionen in
seiner Software zuordnen zu können und auch (nach und nach) zu
verstehen.
Das schreibe ich an David D, ich finde es gut, den Dingen weit auf den
Grund zu gehen. Von mir kenne ich aber auch, daß es oft besser ist,
Teile zu nutzen, die andere Funktionsfähih schon gemacht haben und sich
auf bestimmte Sachen zu konzentrieren, die eben noch nicht wunschgemäß
verfügbar sind.
Ds Risiko, das ein Projekt auf der Strecke bleibt, weil fehlende
Erfolgserlebnisse und steigender Zeitaufwand eben keinen Spaß mehr
machen, ist recht hoch.
PS: Es ist zwar etwas riskant, solchen Source in ein Forum zu packen,
weil der generelle Verriß da dicht daneben steht. Bisher hat man uns ja
in diesem Thread in der Beziehung in Ruhe gelassen. Ich hoffe mal, das
bleibt auch so.
Ich habe mit dem Stand des Codes kein Problem, es ist eben schwer, im
Internet die Vorkenntnisse usw. des Gegenüber einzuschätzen.
Also: David D... Augen zu und durch und nicht die Lust verlieren, das
wird schon.
Gruß aus Berlin
Michael
Michael U. schrieb:> Nanu? Da werden I2C-Clock und I2C-Data hart auf Ausgang und H gesetzt??
Respekt, Respekt: scharfes Auge, Michael !!
> I2C/TWI darf NIE einen festen H-Pegel auf den Leitungen haben, der Slave> darf diese JEDERZEIT auf aktiv L ziehen und das ist dann unlustig für> die Treiber der Beteiligten!
Hmmm - schon erstaunlich, dass bislang weder Kamera noch Arduino Nano
gehimmelt wurden.
Eventuell hat Dich der Levelshifter irgendwie gerettet.
Welchen Typ/Bauteil verwendest Du genau?
Verwendest Du einen I2C Level-Shifter oder einen Feld-Wald-Wiesentyp?
Viele Grüße
Igel1
Einen Feld-Wald-Wiesentyp...
Ich bin leider heute doch nicht mehr dazu gekommen, mir die Links
anzuschauen. Das werde ich morgen nachholen.
Ich habe eben durch absoluten Zufall noch eine schöne
Erklärung/Anleitung zur Programmierung des AVR mit C gefunden, wo einige
Sachen drin standen, die ich auch noch nicht kannte.
http://www.ulrichradig.de/home/uploads/images/Daten_Infos_Anleitungen/AtmelCprogramming.pdf
(insbesondere die "AVR/common" lib. Die macht den Umstieg von Arduino
auf AtmelStudio vermutlich nicht ganz so hart.
Olli hat auf der genannten GitHub Seite schon angefangen die
Informationen zusammenzutragen. Da gibt es echt tolle Möglichkeiten, das
ganze strukturierter und themenbezogener zu diskutieren, weshalb ich da
hier nochmal für Werbung machen wollte :)
Mich hat es auch am Anfang erschlagen, aber mit ein bisschen
ausprobieren kriegt man das schon schnell raus :) Also nur Mut.
https://github.com/igittigitt/ov7670
lg.
David
Hallo,
Andreas S. schrieb:>> Nanu? Da werden I2C-Clock und I2C-Data hart auf Ausgang und H gesetzt??>> Respekt, Respekt: scharfes Auge, Michael !!
ich hatte ja oben extra in Stichpunkten geschrieben, was ich gemacht
habe.
Ich krame gern und oft in fremden Source, man lernt immer wieder
irgendwas oder erkennt eigene Fehler.
>> I2C/TWI darf NIE einen festen H-Pegel auf den Leitungen haben, der Slave>> darf diese JEDERZEIT auf aktiv L ziehen und das ist dann unlustig für>> die Treiber der Beteiligten!>> Hmmm - schon erstaunlich, dass bislang weder Kamera noch Arduino Nano> gehimmelt wurden.
Die ICs sind meist härter im nehmen als man meint. Es ist ja erstmal ein
thermisches Problem für die Ausgangstreiber. Es ist ja auch oft kein
statischer Zustand sondern nur zeitweise Impulse und je nach I2C-Slave
und dessen internem Verhalten muß es nichtmal passieren, daß das
Gegenstück in der Zeit auf Low zieht.
Beim AVR macht man es bei I2C zu Fuß so, daß man über DDR die Pegel
setzt.
SDA und SCL als Init Port auf Low, dann auf Eingang. Der externe PullUp
setzt jetzt den H-Pegel. Für L an SDA/SCl setzt man das Pin im DDR auf
1, damit ist der AVR Pin Ausgang Low. Für H am Ausgang eben DDR-Bit
wieder auf 0 -> Eingang. Ist nach außen dann wie ein OpenDrain.
Allerdings würde ich, wenn vorhanden, immer die TWI-Hardware nehmen. Die
Abfragerei der Zustände, ACK und NACK, Start- Stopcondition sind zwar
simple Abläufe, nur warum soll ich das machen, wenn das schon in die
Hardware gegossen ist.
David D. schrieb:> Ich habe eben durch absoluten Zufall noch eine schöne> Erklärung/Anleitung zur Programmierung des AVR mit C gefunden, wo einige> Sachen drin standen, die ich auch noch nicht kannte.>> http://www.ulrichradig.de/home/uploads/images/Daten_Infos_Anleitungen/AtmelCprogramming.pdf
Ulrich Radig... hatte ich oben schon im Zusammenhang mit meiner alten
Kamera und dem Webserver erwähnt. Müßte so um 2010 gewesen sein.
Auch U.Radig hat mich in der Webserver-Source mal geschafft. Alles recht
brauchbar kommentiert. Dann habe ich eine Pin-Zuordnung o.ä. geändert
und nichts ging mehr. Irgendwo ganz weit unten in einer Funktion hatte
er nicht seine Definition benutzt sondern das Register mit PORTB = 0x23
oder so gesetzt. Sowas war für mich immer Hinweis, in eigenen Sachen
immer auf solche Kelinigkeiten zu achten, Änderungen sofort in allen
Teilen sauber anzupassen solange man eben noch direkt den Kram im Kopf
hat.
Von ihm stammt ja auch die Idee und Realisierung, die DC3840 auf einem
AVR bei 921kBaud auslesen zu können.
Gruß aus Berlin
Michael
Mahlzeit,
>Ulrich Radig... hatte ich oben schon im Zusammenhang mit meiner alten>Kamera und dem Webserver erwähnt.
uups... entschuldige bitte.
Ich habe jetzt einmal angefangen das TWI über das AVR-Interface zu
programmieren. Diesmal habe ich mir alle Mühe gemacht, es sauber zu
kommentieren :D Allerdings habe ich noch keine Erfahrung mit der
Zusammenarbeit beim Coden mit Anderen Teilnehmern gemacht, weshalb ich
euch fragen würde, ob es von der Kommentier Weise, -Umfang ausreichend
ist.
lg. David
Hallo,
David D. schrieb:> uups... entschuldige bitte.
wofür entschuldigst Du Dich? Ich war nur zu faul im Thread hier die
Stelle zu suchen...
Ich schaue nachher mal rein, wenn ich dazu komme. Habe es mal von gitHub
runtergeladen.
Gruß aus Berlin
Michael
David D. schrieb:>> Ich habe jetzt einmal angefangen das TWI über das AVR-Interface zu> programmieren. Diesmal habe ich mir alle Mühe gemacht, es sauber zu> kommentieren :D Allerdings habe ich noch keine Erfahrung mit der> Zusammenarbeit beim Coden mit Anderen Teilnehmern gemacht, weshalb ich> euch fragen würde, ob es von der Kommentier Weise, -Umfang ausreichend> ist.>
Sieht sehr hübsch aus und ich finde die Kommentierung sehr gut.
Zu Deiner Frage im Code:
1
//check if Acknowledge Bit is send by slave
2
if((TWSR & 0xF8) != TW_MT_SLA_ACK) //QUESTION: why do we MASK this with 0xF8 and not with TW_MT_SLA_ACK?
Laut util/twi.h gilt:
1
#define TW_MT_SLA_ACK 0x18
Guckst Du Datenblatt "26.9.2. TWI Status Register", so steht da:
"Note that the value read from TWSR contains both the 5-bit status value
and the 2-bit prescaler value. The application designer should mask the
prescaler bits to zero when checking the Status bits. This makes status
checking independent of prescaler setting."
Will sagen: mit 0xF8 blendest Du die Bits aus, die nicht zur
Status-Anzeige (TWS[7:3]) gehören und mit "!= TW_MT_SLA_ACK" prüfst Du
halt, ob TWS[7:3] genau Deinen gewünschten Wert enthalten - alles andere
ist ein Fehler.
So wäre z.B. auch die Bitfolge "IIII I000" ein Fehler und würde mit o.g.
Code als solcher erkannt. Würdest Du statt mit 0xF8 mit TW_MT_SLA_ACK
maskieren, so würdest Du aus der o.g. Bitfolge "000I I000" machen, was
keine Fehler wäre. Das wiederum wäre ein Fehler :-)
In Summe halte ich die ganze ACK-Prüfung allerdings für falsch, weil
sich genau in diesem Punkt das SCCB-Protokoll vom I2C-Protokoll
unterscheidet.
Daran sind schon sehr viele gescheitert ...
Hier lesen:
https://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/99/t/120548
Und die SCCB-Spec lesen - siehe meine Links weiter oben.
Und hier direkt die nächste Stolperfalle, die zu beachten ist und die
mich seinerzeit viel Zeit gekostet hat:
https://e2e.ti.com/support/embedded/linux/f/354/p/171390/862562#862562
Viele Grüße
Igel1
Hallo,
ich bin gestern nicht dazu gekommen reinzuschauen.
Ich muß auch erstmal genauer in SCCB usw. reinschauen.
Andreas S. schrieb:> In Summe halte ich die ganze ACK-Prüfung allerdings für falsch, weil> sich genau in diesem Punkt das SCCB-Protokoll vom I2C-Protokoll> unterscheidet.> Daran sind schon sehr viele gescheitert ...
Das sehe ich insofern als Problem an, weil man (auch ich) ja
Datenblätter in bestimmten Details erst liest, wenn was klemmt.
Die Entscheidung, ob man ein ACK oder NACK erwartet, wenn man ein Byte
liest oder ob man AC/NACH schickt wenn man Daten empfängt usw, wann man
Start oder Stop setzt usw. passiert ja eigentlich ohnehin abhängig von
den Wünschen eines Slaves. Ein Problem, die TWI-Hardware des AVR zu
nutzen sehe ich im Moment nicht so richtig. Das Statusregister muß man
ja ohnehin sinnvoll auswerten und wenn ACH/NACh mich nicht interessieren
oder ungültig sein können, dann ignoriere ich das Flag eben
entsprechend.
In der einzigen Source, die ich mit der OV7670 am ESP32 real kurz in
Betrieb hatte und die auch lief, benutzt der Programmierer auch die
existierende TWI-Lib. Allerdings auf unterster Ebene, um den Rest
kümmert er sich selbst.
Muß ich mir aber eben alles nochmal zu Gemüte führen.
Gruß aus Berlin
Michael
Hallo Igel,
hallo Michael,
vielen Dank!
Das mit dem Maskieren mit 0xF8 habe ich im Nachgang auch gelesen und
verstanden.
von Michael:
>Ein Problem, die TWI-Hardware des AVR zu>nutzen sehe ich im Moment nicht so richtig.
Ich glaube Igel1 hat sich mit dem ACK-Flag nur auf meinen Code bezogen.
Die Überprüfung habe ich nämlich eben zunächst erst einmal von der
genannten Quelle übernommen. Im Nachgang werde ich jetzt noch prüfen
müssen, ob diese Flags mit dem SCCB überhaupt decken. Vermutlich wie
Igel ansprach eben nicht.
Aber da bin ich gerade dran. Ich möchte das TWI-File so aufbauen, dass
ich es nach Möglichkeit immer nutzen kann, auch für kommende Projekte,
die eventuell nicht auf SCCB-Weise funktionieren. Meine Vorstellung wäre
da zum Beispiel über die initialisieren Funktion Parameter mitzugeben,
bspw. ob Ack gesendet wird oder nicht.
Haltet ihr das für machbar (im ertragbaren Rahmen).
Und würdet ihr das TWI direkt über Interrupts machen oder erst den
"normalen" weg?
lg. David
PS: OpenDrain habe ich jetzt auch endlich mal gerafft. Ist ja eigentlich
relative einfach :D ... Sobald man verstanden hat, dass man über einen
Eingangs-Pin indirekt den Leitungspegel beeinflussen kann.
David D. schrieb:> Aber da bin ich gerade dran. Ich möchte das TWI-File so aufbauen, dass> ich es nach Möglichkeit immer nutzen kann, auch für kommende Projekte,> die eventuell nicht auf SCCB-Weise funktionieren. Meine Vorstellung wäre> da zum Beispiel über die initialisieren Funktion Parameter mitzugeben,> bspw. ob Ack gesendet wird oder nicht.> Haltet ihr das für machbar (im ertragbaren Rahmen).
Ich selber komme zunehmend weg vom "one code fits all"-Ansatz.
Ich würde mir separate Bibliotheken für SCCB und I2C machen.
Nächstes Thema:
In Punkto ACK/NACK musst Du evtl. ein bißchen aufpassen, ob Du
Deine Hardware mit ACK konfigurierst. Dann könnte es passieren,
dass die Hardware eine gewisse Zeit auf das ACK-Bit wartet und
in dieser Zeit quasi "hängt" (bis zum timeout).
Besser ist es vermutlich, Dein I2C/TWI-Hardwaremodul direkt so
zu konfigurieren, dass es kein ACK erwartet.
Aber hier würde ich den Ansatz "Studieren geht über Probieren" fahren.
> Und würdet ihr das TWI direkt über Interrupts machen oder erst den> "normalen" weg?
Über den "normalen" Weg - gerade bei der Kamera ist das völlig okay,
denn die wird ja sowieso zuerst konfiguriert und dann erst richtig
genutzt.
Viele Grüße
Igel1
David D. schrieb:> PS: OpenDrain habe ich jetzt auch endlich mal gerafft. Ist ja eigentlich> relative einfach :D ... Sobald man verstanden hat, dass man über einen> Eingangs-Pin indirekt den Leitungspegel beeinflussen kann.
... das wiederum habe ich nicht verstanden??
Im OpenDrain-Konzept kannst Du nichts über einen Eingangspin
beeinflussen.
Oder meintest Du den etwas schrägen Workaround, mit dem man im Atmega so
ein OpenDrain "simuliert"? (by the way: im ARM kann man die I/O Pins in
einen OpenDrain-Mode setzen und muss dann keine Klimmzüge machen).
Unter'm Strich hast Du halt nur einen Widerstand, der an Vcc
angeschlossen wird und an dessen unterem Ende Du die
Collector-Emitter-Strecke (oder die Drain-Source Strecke) beliebig
vieler Devices gegen Masse anschließt.
Jedes der Devices kann dann das Potential an diesem unteren Ende des
Widerstandes gegen Masse ziehen.
By the way: SCCB ist laut Datenblatt auch elektrisch kein I2C-Bus,
siehe SCCB-Spec hier:
http://www4.cs.umanitoba.ca/~jacky/Teaching/Courses/74.795-LocalVision/ReadingList/ov-sccb.pdf
Dort: Figure 22, Figure 23 und Figure 24.
Dort wird der Bus aktiv getrieben (mit push-pull Schaltungen am Ausgang
von Master UND Slave).
Um das Schlimmste zu vermeiden, gibt es einen "conflict-protection
resistor", der evtl. auch des Rätsels Lösung dafür sein könnte, dass Du
in Deiner ursprünglichen Beschaltung weder OV7670 noch AVR gegrillt
hast. Ich vermute, dieser conflict-protection resistor steckt irgendwo
auf dem OV7670 board.
Nevertheless - man kann SCCB mit I2C-Treibern bedienen, das haben schon
viele Leute in der Praxis bewiesen. Aber 100% Spec-konform ist es meiner
Meinung nach nicht.
Viele Grüße
Igel1
Andreas S. schrieb:> Im OpenDrain-Konzept kannst Du nichts über einen Eingangspin> beeinflussen.> Oder meintest Du den etwas schrägen Workaround, mit dem man im Atmega so> ein OpenDrain "simuliert"? (by the way: im ARM kann man die I/O Pins in> einen OpenDrain-Mode setzen und muss dann keine Klimmzüge machen).
Okay? vielleicht habe ich es dann doch nicht verstanden?
Der Punkt ist doch, dass der High-Pegel durch den Pull-Up und nicht
durch den Ausgang des Controllers entsteht.
Um das zu erreichen bleibt mir doch nur, den Pin des Controllers auf
Eingang zu schalten (hohe Impedanz am Pin).
Habe meine Erkenntnisse heute morgen hier mal zusammengefasst:
https://github.com/igittigitt/ov7670/wiki/unsorted
wenn das falsch ist, bitte unbedingt bescheid geben. Dann muss ich das
wieder löschen oder korrigieren.
lg.
David
Hallo,
Andreas S. schrieb:> Um das Schlimmste zu vermeiden, gibt es einen "conflict-protection> resistor", der evtl. auch des Rätsels Lösung dafür sein könnte, dass Du> in Deiner ursprünglichen Beschaltung weder OV7670 noch AVR gegrillt> hast. Ich vermute, dieser conflict-protection resistor steckt irgendwo> auf dem OV7670 board.
Ich müßte mein Modul mal genauer mit der Lupe begutachten.
> Nevertheless - man kann SCCB mit I2C-Treibern bedienen, das haben schon> viele Leute in der Praxis bewiesen. Aber 100% Spec-konform ist es meiner> Meinung nach nicht.
Auf den Ausgangsüunkt des Threads bezogen hat das jetzt eine Art
"logistisches" Problem: man sollte für den SCCB tatsächlich spezielle
Routinen schreiben, das wäre sauber. Man kann die Kamera auch insofern
nicht als I2C-Device betrachten, weil man sie nicht mit anderen
i2C-Slaves an diesem Bus zusammen betreiben kann.
Problem ist, daß man sich darüber klar sein sollte, daß man das dann
speziell für diese Kamera und ähnliche Kamera-ICs macht. Je nach
späteren Absichten kommt man damit vielleicht nie wieder in Berührung.
Ich habe sowas früher öfter für irgendwelche UKW/rundfunk-ICs gemacht,
die PLLs dort hatten immer irgendwelche eigenen seltsamen Protokolle.
Sowas habe ich allerdings dann immer sehr direkt und hart gecodet mit
Pingewackel usw. Das hat bei mir auch nie einen universellen Überbau
bekommen weil es nicht sinnvoll allgemein nutzbar war.
Gruß aus Berlin
Michael
David D. schrieb:> Okay? vielleicht habe ich es dann doch nicht verstanden?> Der Punkt ist doch, dass der High-Pegel durch den Pull-Up und nicht> durch den Ausgang des Controllers entsteht.> Um das zu erreichen bleibt mir doch nur, den Pin des Controllers auf> Eingang zu schalten (hohe Impedanz am Pin).>> Habe meine Erkenntnisse heute morgen hier mal zusammengefasst:> https://github.com/igittigitt/ov7670/wiki/unsorted>> wenn das falsch ist, bitte unbedingt bescheid geben. Dann muss ich das> wieder löschen oder korrigieren.
Nein, Entwarnung: Du hast alles richtig verstanden und Dein
github-Dokument beschreibt es ebenfalls richtig.
Evtl. möchtest Du noch erwähnen, das ein solcher I2C-Bus niemals aktiv
auf hight geschaltet werden sollte, weil sonst die hier
(http://www4.cs.umanitoba.ca/~jacky/Teaching/Courses/74.795-LocalVision/ReadingList/ov-sccb.pdf)
in Figur 24 erwähnte Konstellation auftritt - allerdings ohne den dort
eingezeichneten Widerstand ...
Viele Grüße
Igel1
Hallo zusammen,
entschuldigt bitte die rare Informationspolitik meinerseits.
Dadurch, dass wir es ja jetzt über das TWI-Interface des AVR gehen
wollen, stehe ich quasi wieder am Anfang und versuche mit dem SCCB zu
kommunizieren ;-) senden funktioniert soweit auch schon, jetzt bin ich
grade an der Read-Funktion.
War aber das ganze Wochenende, sowie die kommende Woche komplett zu
geplant, sodass es von meiner Seite aus erst frühestens am Sonntag Abend
neue Erkenntnisse gibt.
aktuellen Stand habe ich grade auf das TWI-branch gepushed. kann man
sich also in Github anschauen.
Ich nehme auch gerne Vorschläge entegen :) grade habe ich einfachmal die
Kontrolle des ACK-Bits übersprungen.
lg.
David
Hallo,
ich habe mir das mal von github geholt.
Ich werde einfach mal Deine TWI-Sachen kopieren und eine "echte"
SCCB-Version in der ArduinoIDE machen und für mich speziell auf dem
ESP32 testen.
Dann kann ich das erstmal ohne Änderungen für den Arduino Nano (Mega328)
oder eben den ESP32 compilieren.
Außerdem kann ich dann am Mega328 auch Deine version und meine zusammen
mit Kamera und logicAnalyzer vergleichen, falls die Kamera nicht
erwartungsgemäß antwortet.
Die pinMode()/digitalWrite()/digitalRead() der ArduinoIDE dann duch die
Port/Pin-Zugriffe des AVR zu replacen ist ja keine wirkliche Arbeit.
Gruß aus Berlin
Michael
Hi David, (und Michael),
@David: Danke für das Lebenszeichen - dann wissen wir, dass es hier in
ca. 2 Wochen weitergeht (es sei denn Olli bekommt Lust, den Stier bei
den Hörnern zu packen ...).
Ansonsten: kein Problem - in diesem Thread sind wir ja alle nur
Hobbyisten und haben Zeit.
Ich selber bin eh nur "Zaungast" bei Euch, denn mein OV7670 läuft an
einem STM32F429 - ARM-Prozessor, der das Einlesen quasi "nebenbei" mit
seiner Peripherie macht. Da will man nicht mehr zurück zum AVR - sorry.
Daumen hoch aber für Michael, der sich hier so engagiert einbringt.
Ich habe hier ebenfalls einen ESP32 rumliegen und bislang noch nichts
damit gemacht (keine Zeit). Kannst Du mir ein netterweise paar Tipps zur
Einarbeitung geben? (okay, ist etwas off-topic, aber ein paar
Stichpunkte wären einfach gut: IDE? Gute Einstiegs-URL's, was muss man
unbedingt lesen, ...)
Viele Grüße
Igel1
Hallo,
Andreas S. schrieb:> Ich habe hier ebenfalls einen ESP32 rumliegen und bislang noch nichts> damit gemacht (keine Zeit). Kannst Du mir ein netterweise paar Tipps zur> Einarbeitung geben? (okay, ist etwas off-topic, aber ein paar> Stichpunkte wären einfach gut: IDE? Gute Einstiegs-URL's, was muss man> unbedingt lesen, ...)
ein wunder Punkt... Ich hatte bei Erscheinen mir ziemlich schnell damals
ESP6266 gekauft. Die vorgefertige ID in einer VM (so von Espressif
damals bereitgestellt) auf den Rechner geworfen und grrr... nichts ging,
nichts klappte, Doku zu den ESP in gutem Chinesich oder lustigem aber
unbrauchbarem Englisch.
Sie haben dann sehr schnell gelernt und parallel dazu kam die Einbindung
des SDK in die ArduinoIDE. Das war eigentlich mein Grund für die
Bekanntschaft mit dieser IDE. Mindestnes 2 der Programmierer, die damals
die Arduino-Anbindung gebaut haben, arbeiten inzwischen fest für
Espressif, deshalb ging es beim ESP32 auch viel schneller mit dem
Anpassen usw.
Damit hast Du jetzt eigentlich 2 Wege: auf
https://www.espressif.com/en/products/hardware/esp32/overview findest Du
alles, was es dazu vom Hersteller gibt, die SDKs usw.
Ich bin da aber nicht direkt auf dem laufenden.
Ich nutze den ESP32 zusammen mit der ArduinoIDE.
https://github.com/espressif/arduino-esp32
Die Einbindung und Anpassung ist aber da noch nicht 100% und man kann
einige Möglichkeiten auch (noch?) nicht nutzen. Dafür spielt das in 20
Minuten und man hat ein Erfolgserlebnis und für meine kleinen Projekte
reicht es mit Sicherheit.
Alles nützliche gibt es jetzt ohnehin bei github.
https://github.com/espressif
Der ESP32 ist eigentlich recht genial gerade für kleine Projekte weil er
fast alles an Hardwareanbindungen drin hat was man gebrauchen kann.
Gruß aus Berlin
Michael
Sorry, ich glaube das aktuellste ist jetzt erst oben. Hab wohl vergessen
nen Knopf zu drücken...
Vielen Dank, dass du das machst.
Ganz kurze Frage: kann ich mir durch die Lvl-Shifter eigentlich die
Pull-Up Widerstände auf den Bus-Leitungen sparen? bzw. brauche ich sonst
auf jeder Seite einen?
lg.
David
Beim Levelshifter benötigst Du keine zusätzlichen Pullups.
Ich werde mir Deinen TWI Code auch mal vornehmen und die Timings mit dem
Datenblatt vom SCCB vergleichen. Die müssen ja nicht SPI entsprechen.
Zum Glück ist das SCCB ja eh nur ein Subset von SPI, einfaches
Master/Slave. Das macht den zu verwendenden Code schlanker.
Ich bin auch eher ein Freund davon die Dinge optimal an die Verwendung
anzupassen, also keine Rundum-Sorglos-Für-Alles Libs. Die haben nur
massig Implikationen due man kennen muss und die Fehlersuche ist ein
Graus.
Warum auch nicht eine hochspezialisierte SCCB Lib machen?
Echter AVR Code dürfte auch um einiges schlanker sein als mit Arduino
Framework drumherum. Ich habe es inzwischen (tataaa) auch geschafft das
AVR Studio zu installieren. Nachdem ich wirklich erstmal ALLE Windows
Visual C* Bibliotheken von meinem PC gelöscht habe. Da hatteb sich
inzwischen gute 20 Stück angesammelt und irgendwie dafür gesorgt das die
IDE nicht mehr die benötigte findet.
Bin also jetzt auch mit am Start :-) Lass uns erst dieses doofe SCCB
Dong rocken, damit es ordentlich weitergehen kann.
Ich denke, sobald wir mal ein Bild irgendwie rüber haben sollteb wir auf
die FIFO Version wechseln, sonst ist mit AVR schnell schluß.
Hallo,
Olli Z. schrieb:> Die müssen ja nicht SPI entsprechen.> Zum Glück ist das SCCB ja eh nur ein Subset von SPI, einfaches> Master/Slave.
nun verwirre ihn nicht völlig, I2C, nicht SPI...
Olli Z. schrieb:> Warum auch nicht eine hochspezialisierte SCCB Lib machen?
Prinzipiell ist es kein Problem SCCB mit BitBanging auf dem AVR zu
machen, ein Problem sehe ich eher darin, daß es eingentlich keiner
wirklich braucht. SCCB ist eben als Kamera-Protokoll gebaut worden,
zumindest habe ich nichts anderes gesehen. Man wird aber gerade die
nicht wirklich zusammen an einem AVR nutzen können, der OV7670 wird wohl
eine Ausnahme bleiben, weil ein netter China-Hersteller die Dinger noch
rumliegen hatte und ein breakout-Board drum gebastelt hat...
> Echter AVR Code dürfte auch um einiges schlanker sein als mit Arduino> Framework drumherum.
Mit dem Arduino Framework ist es so eine Sache, wenn ich seine Dateien
in einen Ordner OV7670_Kamera im Sketchbook anlege und die main.c in
OV7670_Kamera.ino umbenenne, kümmert sich das Arduino Framework ganz
brauchbar um das, was es da findet. Sinnigerweise mault er dann über
bool weil in älteren AVR-Studio (4.xx) und GCC-Versionen die noch mit
#include <stdbool.h> selber eingebunden werden mußte. Habe ich eben
hinzugefügt, dann läuft der Compiler komplett durch, 134 Bytes Code.
In das alte Atmel-Studio 4.18 geworfen sind es 196 Bytes. Da könnte ich
mir jetzt die erzeugten ASM-Files von beiden mal anschauen, ich denke
aber, da ist der uraltete GCC von 2010 im uralten Atmel-Studio schuld,
die neueren optimieren merklich besser.
Ein neueres AVR-Studio hatte ich nur mal kurz drauf, ich brauche es für
meine Projekte ("Spielereien") im Moment nicht wirklich.
Das sieht alles völlig anders aus, wenn man beruflich nutzen will oder
die Projekte richtig groß werden oder eben µC aus aktuelleren
Entwicklungen nutzen will oder muß.
Ansonsten sind es aber eben alles Grundlagen, eine Timer bleibt ein
Timer, egal wieviele Sonderfunktionen und Modi er hat, ein IO ist ein
IO, ob ich da wie beim AVR den Mode direkt setzen kann oder noch einer
komplexe IO-Matrix erklären muß, welche interne Hardware jetzt an
welchem Pin landen soll (XMega, ESP32 usw.). I2C, SPI, I2S, CAN, ...
sind Sachen, die sind Funktionen, wo ich wissen muß (sollte) wie das
Protokoll funktioniert, was an Spezialitäten jeweils dazugehören und wie
ich die benutzen kann.
An welchen Registern ich drehen muß, wenn es Hardwareunterstützung im µC
dazu gibt oder wie weit die geht (ich sage nur USI beim AVR, kann vieles
nund nichts vollständig), das muß ich ohnehin aus dem Datenblatt,
Applicationsbeispielen des Herstellers des konkreten µC zusammensuchen.
Der Kram ist ohnehin hier ein netter Versuchsaufbau für mich, ich werde
nachher mal meinen (auch alten und selbstgebauten) LA ranklemmen, das
kann dann so erstmal hier liegenbleiben zum mitmachen.
http://www.avr.roehres-home.de/logikanalyzer/index.html
Und auch die Webseite ist uralt und ungepflegt. ;)
Gruß aus Berlin
Michael
Michael U. schrieb:> ein wunder Punkt... Ich hatte bei Erscheinen mir ziemlich schnell damals> ESP6266 gekauft.
Ich ebenfalls - allerdings den ESP8266 ;-)
Zum Glück bin ich etwas später eingestiegen, aber nicht nur die
Software, auch die Hardware hat dort üble Bugs: so mußte ich viele
Stunden verbraten um herauszufinden, dass das WLAN-Modul die
Meßergebnisse des AD-Wandlers beeinflußt - super Möhre ... Erst wenn
man Wake-Up beim WLAN deaktivierte stimmten die Ergebnisse wieder - ohne
Worte ...
> Sie haben dann sehr schnell gelernt und parallel dazu kam die Einbindung> des SDK in die ArduinoIDE.
Ja, habe den ESP8266 sowohl in LUA als auch in Arduino programmiert.
Lämpchen ein-/aus geht ganz gut, aber auf anspruchsvollere Dinge möchte
ich mich mit so einem halbgaren Teil nicht einlassen - da fressen einen
die Bugs auf.
> Damit hast Du jetzt eigentlich 2 Wege: auf> https://www.espressif.com/en/products/hardware/esp32/overview findest Du> alles, was es dazu vom Hersteller gibt, die SDKs usw.> Ich bin da aber nicht direkt auf dem laufenden.
Danke!
> Ich nutze den ESP32 zusammen mit der ArduinoIDE.> https://github.com/espressif/arduino-esp32
Danke!
> Die Einbindung und Anpassung ist aber da noch nicht 100% und man kann> einige Möglichkeiten auch (noch?) nicht nutzen. Dafür spielt das in 20> Minuten und man hat ein Erfolgserlebnis und für meine kleinen Projekte> reicht es mit Sicherheit.
Geht mir manchmal ähnlich.
> Alles nützliche gibt es jetzt ohnehin bei github.> https://github.com/espressif
Danke!
> Der ESP32 ist eigentlich recht genial gerade für kleine Projekte weil er> fast alles an Hardwareanbindungen drin hat was man gebrauchen kann.
Bin jetzt eine Woche auf (Dienst)reise - ideal zu abendlichen Proggen -
und ich wollte eigentlich das kleine Tütchen mit dem ESP32 eingepackt
haben. Nun sitze ich im Zug und was zu Hause liegt ist der ESP32 -
grrrr....
Danke aber nochmals für Deine Tipps!
Viele Grüße
Andreas
Michael U. schrieb:> nun verwirre ihn nicht völlig, I2C, nicht SPI...
Ups, Du hast natürlich recht, mein Fehler.
> Olli Z. schrieb:>> Warum auch nicht eine hochspezialisierte SCCB Lib machen?> Prinzipiell ist es kein Problem SCCB mit BitBanging auf dem AVR zu> machen, ein Problem sehe ich eher darin, daß es eingentlich keiner
Ich meinte das schon unter Zuhilfenahme des I2C-Interfaces vom AVR, nur
eben das wir nicht die fertige Wire-Lib nehmen, sondern das für unsere
Zwecke abspecken.
> zumindest habe ich nichts anderes gesehen. Man wird aber gerade die> nicht wirklich zusammen an einem AVR nutzen können, der OV7670 wird wohl
Jab, die Erkenntnis ist ja bereits gefestigt. Da werden wir nur mit FIFO
halbwegs was rausbekommen. Einzige Option wäre ggf. noch ein lokal am
AVR angeschlossenes LCD-Display, welches die empfangenen Daten der
Kamera direkt darstellt. Aber auch das wird nur in einer sehr
reduzierten Auflösung/Framerate möglich sein.
> hinzugefügt, dann läuft der Compiler komplett durch, 134 Bytes Code.> In das alte Atmel-Studio 4.18 geworfen sind es 196 Bytes. Da könnte ich
Wow, das ist wirklich wenig, hätte ich nicht mit gerechnet. Da könnte
man ja sogar noch das ASM "verstehen" ;-)
> Ein neueres AVR-Studio hatte ich nur mal kurz drauf, ich brauche es für> meine Projekte ("Spielereien") im Moment nicht wirklich.
Ich hoffe das wir mit verschiedenen Versionen keine Probleme bekommen.
Ich würde halt immer das aktuelle nehmen, also jetzt 7.
> Der Kram ist ohnehin hier ein netter Versuchsaufbau für mich, ich werde
Ich bin aber echt froh einen Vollblut-Programmierer hier im Thread zu
haben. Meine Kenntnisse sind an vielen Stellen nur rudimentär. Ach, es
gibt ja so wahnsinnig viel interessantes Zeug und so wenig Zeit ;-)
Als LA habe ich mir mal für nen 20er einen Saleae-Logic mit 8-Kanal
zugelegt. Die Software finde ich ganz gut, hat auch Protokoll-Analyzer
mit drin und billiger gehts kaum. Für Hobby, Spiel und Spaß genau
richtig. Einzig das der nur für TTL-Level ausgelegt ist, also einen
Vref-Eingang hat. 3,3V geht damit aber auch noch.
Michael U. schrieb:> Der Kram ist ohnehin hier ein netter Versuchsaufbau für mich, ich werde> nachher mal meinen (auch alten und selbstgebauten) LA ranklemmen, das> kann dann so erstmal hier liegenbleiben zum mitmachen.> http://www.avr.roehres-home.de/logikanalyzer/index.html> Und auch die Webseite ist uralt und ungepflegt. ;)
Wow - bin sehr beeindruckt: ein selbstgebauter LA mit
selbstprogrammierter Software! Nicht schlecht!
Ich selber habe einen 500MHz Intronix Logicport - ganz schnöde hier im
Forum erstanden. Im Gegensatz zu Deinem Selbstbau also Coolnessfaktor =
0,ist aber trotzdem eine der besten Investitionen in meinem Bastelpark.
Viele Grüße
Igel1
Hallo,
Andreas S. schrieb:> Ja, habe den ESP8266 sowohl in LUA als auch in Arduino programmiert.> Lämpchen ein-/aus geht ganz gut, aber auf anspruchsvollere Dinge möchte> ich mich mit so einem halbgaren Teil nicht einlassen - da fressen einen> die Bugs auf.
was ist anspruchsvoll? Hier läuft ein gutes Dutzend ESP8266 dauerhaft
und stabil. Als NTP-Client für ein paar Uhren weil DCF77 hier
mittlerweile zuviel Ärger macht. Am PIR-Sensor zum Melden einer
Bewegung. Als IR-Send-Bridge um den alten Sony-Receiver per IR und MQTT
steuern zu können. Als Warner wil ich im Bad mal wieder das Licht
angelassen habe. In WLAN-Steckdosen von Sonff und Norma/Obi. Als
433MHz-bridge nach MQTT für meine alten Eigenbausensoren. Als Steuerung
für einen WS2812LED-Stripe. Bin gerade einfach mal so durchgegangen, in
solchen Dingen sehe ich den Zweck der ESP8266 gerade durch den Preis.
Einen MP3-Streamplayer mit einem VS1053 gibt es auch noch, prizipiell
stabil, durch den etws knappen Ram aber hier im WLAN manchmal zu
Aussetzern neigend, war auch eher ein proof-of-concept weil das Zeug
rumlag.
Da wird ein ESP32 einziehen, dank mehr Ram und stabil laufendem
Software-MP3-Decoder und I2S-Ausgabe besser geeignet.
Für (unangenehme) Überraschungen ist der ESP32 aber auch noch eine Weile
gut...
Olli Z. schrieb:> Ich bin aber echt froh einen Vollblut-Programmierer hier im Thread zu> haben. Meine Kenntnisse sind an vielen Stellen nur rudimentär. Ach, es> gibt ja so wahnsinnig viel interessantes Zeug und so wenig Zeit ;-)
Hmmm... Vollblut-Programmierer... Ich sage es mal so: ein Projekt zu
haben, das in seine sinnvollen Abschnitte zu zerlegen, Lösungsansätze
für die Teilprobleme zu finden, Datenblätter lesen und verstehen zu
können, kein Problem. Assembler kein Problem. C geht, oft schreibe ich
da aber eher ASM-Abläufe, nutze also die C-Vorteile nicht immer aus
(Struktur, Union, Bitfelder usw. usw.). C++ nur duch Arduino, keine
wirkliche Erfahrung mit Klassen usw.
Das SCCB nagele ich wahrscheinlich hier mit dem Datenblatt der OV76770
in 2 Stunden stabil in AVR-ASM zusammen, in C vermutlich auch, da kommen
dann aber sicher 10 Leute, die sagen, daß man das doch in C viel
eleganter mit nutzung aller Möglichkeiten von C machen kann...
Olli Z. schrieb:> Wow, das ist wirklich wenig, hätte ich nicht mit gerechnet. Da könnte> man ja sogar noch das ASM "verstehen" ;-)
vermutlich lese und verstehe ich das ASM schneller als den Inhalt einer
C++-Klasse. ;)
Olli Z. schrieb:> Ich hoffe das wir mit verschiedenen Versionen keine Probleme bekommen.> Ich würde halt immer das aktuelle nehmen, also jetzt 7.
Für mich sehe ich da in diesem Zusammenhang keine wirklichen Probleme.
Ich kopiere nur die .c und .h Dateien in mein angelegtes Projekt, egal
ob Arduino oder Atmel-Studio und lasse den Compiler meckern. Ist
normalerweis in diesem Umfang in 10 Minuten angepasst, Änderungen an den
eigentlich Sourcen sollten nicht nötig sein und Sachen wie das mit dem
#include <stdbool.h> sind über verscheiden versionen ohnehin üblich.
Sollte auch das aktuelle Studio nicht stören, wenn das drinsthen würde.
Vielleicht gäbe es eine Warnung über eine doppelte Deklaration...
Gruß aus Berlin
Michael
Hi,
gemäß Implementation Guide v1.0 (Chapter 8) soll man ja zunächst einen
Reset-Command an Adresse 0x12 (auch "COM7" genannt) absetzen, indem man
dort das Bit 7 auf 1 setzt (in Summe also eine 0x80 sendet).
Die SCCB-Abfolge dazu ist:
0.) I2C-Startabfolge senden (SDA geht von High auf Low während
SDC High ist)
1.) I2C-Adresse des OV7670 (nämlich 0x21) anpiepsen
und Schreiboperation signalisieren.
Die ersten 7 Bit [7:1] codieren die 0x21 und das achte Bit [0] wird
auf "0" gesetzt, um eine Schreiboperation zu signalisieren.
In 8-Bit Schreibweise ergibt sich somit eine 0x42, die da
gesendet wird.
2.) I2C-Register senden (nämlich 0x12)
3.) Registerwert senden (nämlich 0x80)
4.) I2C-Stopabfolge senden (SDA geht von Low auf High während
SDC High ist)
Diesen Vorgang habe ich einmal mit meinem LogicAnalyzer mitgeschnitten
und hier als Bild angehängt (interessant: mein OV7670 scheint irgendwie
doch ein ACK zu senden).
Viele Grüße
Igel1
Ach ja: und noch ein Stilbild von meinem traurigen Dasein in einem Hotel
- dokumentiert mit einer OV7670.
Das Bild ist in Wirklichkeit etwas schärfer als hier hochgeladen, aber
mit einem Handy ein Bild von einem TFT-Display zu machen, ist halt nicht
so der Hit. Außerdem habe ich die automatische Verkleinerung beim
Hochladen in das Forum nicht deaktiviert - das Verschlimmert die
Qualität nochmals.
Viele Grüße
Igel1
Hallo,
Andreas S. schrieb:> Diesen Vorgang habe ich einmal mit meinem LogicAnalyzer mitgeschnitten> und hier als Bild angehängt (interessant: mein OV7670 scheint irgendwie> doch ein ACK zu senden).
irgendwo wohl in der SCCB-Doku stand eine Anmerkung wovon dieses Bit
beeinflußt wird, es kann als 0 oder 1 kommen, ist aber kein ACK. Ich
glaube, da stand auch in einem Diagramm was von Don't Care. Wer darf es
nicht ändern? ich? Der SCCB-Slave? Muß ich sowieso nochmal reinschauen,
auf Anhieb finde ich es jetzt nicht...
Andreas S. schrieb:> Ach ja: und noch ein Stilbild von meinem traurigen Dasein in einem Hotel> - dokumentiert mit einer OV7670.
Den Finger nicht im Bild und noch was auf den glasboden gelegt, dann ist
der Stil sicher "Stillleben".
Gruß aus Berlin
Michael
Andreas S. schrieb:> Olli Z. schrieb:>> Beim Levelshifter benötigst Du keine zusätzlichen Pullups.> Sicher?
Ja, so einen hab ich auch. Das ist von der Schaltung her wohl sowas wie
„der Klassiker“. Ist auch hier in der Forums Knowledgebase so drin:
https://www.mikrocontroller.net/articles/Pegelwandler
Die Pullups sind da ja deutlich zu erkennen :-)
Und dann gibt es noch zahlreiche ICs für sowas. Z.B.
https://www.adafruit.com/product/395 ein 8fach Bi-Direktional. Ebenso
liefert die 74er Serie auch etliche Shifter, teils Uni (74540), teils
auch Bi-Direktional wie der 74AVCH2T45. Die Auswahl ist riesig...
Hallo,
Olli Z. schrieb:> Die Pullups sind da ja deutlich zu erkennen :-)
ob 10k im Zweifel niedrig genug sind muß man schauen. Hängt letztlich
eben von der Anzahl Slaves ab und von den Leitungslängen. Bei den
üblichen "basteleien geht es eigentlich immer so. Di Schaltung war schon
ein Vorschlag in einem alten Philips I2C-Dokument.
Ich bin beim Experimentieren da immer recht großzügig, man muß nur im
Hinterkopf haben, welche Bedeutung die PullUps bei I2C haben.
Sonst sucht man schnell mal die selbst eingebauten Fehler. Da kann man
mal schnell 2,2k zusätzlich ranhängen, wenn es nichts ändert sollte man
die richtige Ursache suchen. ;)
Gruß aus Berlin
Michael
Andreas S. schrieb:> Ein STM32F429I-Discovery-Board bekommt man für ca. 20-25 EUR in der> Bucht.> Dort ist neben einem potenten stm32f429-Prozessor auch schon ein> ILI9346-Display drauf - optimal zum Experimentieren mit dem OV7670
... kleine Korrektur zu meinem alten Post:
Es handelt sich natürlich nicht um eine ILI9346 sondern um ein
ILI9341-Display.
Viele Grüße
Igel1
Hallo :)
ich möchte ein kurzes Lebenszeichen absenden :)
Ende dieser Woche bin ich hoffentlich wieder in der Lage mit zu basteln,
proggen etc.
Der selbstgebaute Logic-Analyzer wäre mal einen Nachbau wert um auch
einen zu besitzen.
mein Level-Shifter ist dieser hier:
https://www.roboter-bausatz.de/434/i2c-pegelwandler/level-konverter-3.3v-5v-bidirektional-2-kanal
gibt es schon fortschritte in Sachen Kommunikation mit dem SCCB mittels
des TWI(I2C)-Interface am AVR?
lg. David
David D. schrieb:> Hallo :)> ich möchte ein kurzes Lebenszeichen absenden :)
Nett von Dir!
> Ende dieser Woche bin ich hoffentlich wieder in der Lage mit zu basteln,> proggen etc.>> Der selbstgebaute Logic-Analyzer wäre mal einen Nachbau wert um auch> einen zu besitzen.
Wenn's um den reinen Bastelerfolg geht: do it!
Wenn's Dir nur um die Messmöglichkeiten als solches geht: don't do it!
Hintergrund: für 100 - 200 EUR bekommst Du auf dem Markt LA's, für
deren Funktionalität Du mindestens 2-3 Jahre designen und proggen
müsstest.
Meinen 500MHz LogicPort von Intronix bekommst Du derzeit gebraucht
z.B. für um die 100-130 EUR (neu für ca. 170 EUR).
Sealae soll auch sehr gut sein - ob man den Clone nimmt, muss jeder
mit seinem Gewissen klar- oder eben nicht klarmachen.
> mein Level-Shifter ist dieser hier:> https://www.roboter-bausatz.de/434/i2c-pegelwandler/level-konverter-3.3v-5v-bidirektional-2-kanal
Hmmm ... kann leider keinen Schaltplan finden.
Aber 2 MOS-Transistoren deuten auf dasselbe Prinzip wie beim oben
verlinkten Pegelwandler von Sparcfun hin.
Was allerdings der VLDO auf der Platine soll, ist mir etwas unklar.
Schaltplan wäre schon schön.
> gibt es schon fortschritte in Sachen Kommunikation mit dem SCCB mittels> des TWI(I2C)-Interface am AVR?
Ich fühle mich einfach mal nicht angesprochen, weil ich ja nur Zaungast
bin und weiterhin beim ARM-Prozessor bleiben werde (... ich muss einfach
nur abwarten, bis Ihr die Nase von den AVR-Einschränkungen voll habt und
dann ebenfalls auf den ARM schwenkt :-)
Anyway - habe Euch oben einmal einen Mitschritt meines STM32F429 bei
seiner Kommunikation mit dem OV7670 angehängt - macht die Zs.hänge etwas
"greifbarer".
Viele Grüße
Igel1
PS: habe mir soeben das gebrauchte Dragon-Board hier aus dem MC-Markt
für 25€ geschnappt (nur für den Fall, dass ich doch noch mitspielen will
...)
Kann für den Hausgebrauch einen Saleae nur empfehlen. Günstig und die
Software ist leicht zu bedienen und kann was. Bin mit meinem 20€ Clone 8
Kanal 20 Mhz hochzufrieden.
Hallo, kurzes Lebenszeichen.
Ich komme leider nicht mehr meinen To-Dos für meine Abschlussarbeit und
den Job-Bewerbungen hinter her.
Ich hoffe, dass sich das in den nächsten Wochen legt und ihr trotz des
vermutlich aufkommenden Sommers nicht die Lust verliert.
Ich werde an dem Thema dran bleiben und weiterarbeiten sobald ich auch
nur ein bisschen Zeit übrig habe!
Aber grade muss ich eben erst einmal meinen Abschluss sichern ;-) ich
hoffe ihr versteht das!
liebe Grüße
David
@Olli, wie siehts bei dir aus? nachdem das AtmelStudio ja jetzt bei dir
läuft. hast du schon Neuigkeiten zur Kommunikation mit dem SCCB übers
TWI-Interface?
Hallo,
David D. schrieb:> Aber grade muss ich eben erst einmal meinen Abschluss sichern ;-) ich> hoffe ihr versteht das!
wäre mir auch wichtiger gewesen, damals... ;)
Ich habe im Moment auch nichts weiter mit der Kamera gemacht, andere
"sinnlose" Projekte hatten/haben erstmal Vorrang. Liegt aber noch alles
griffbereit. Wie ich mich kenne, wird es nur eine Frage der Zeit sein,
bis ich mich da wieder dran festbeiße.
Gruß aus Berlin
Michael
> Aber grade muss ich eben erst einmal meinen Abschluss> sichern ;-) ich hoffe ihr versteht das!
Kommt drauf an: Wenn der Abschluß "Professur" oder "Doktor" heißt,
dann fände ich es doch wichtiger, das Projekt hier erst einmal sauber
abzuschliessen ...
Wenn's allerdings um den Schul- oder Lehr-Abschluss geht, dann ist
der natürlich wichtiger.
Good luck!
Igel1
Andreas S. schrieb:> Kommt drauf an: Wenn der Abschluß "Professur" oder "Doktor" heißt,> dann fände ich es doch wichtiger, das Projekt hier erst einmal sauber> abzuschliessen ...
Da Du offensichtlich weder das Eine noch das Andere vorhast wärst Du
doch prädestiniert :-) - ich würde auch eher einen Doktortitel erwerben
(einen Professorentitel erwirbt man i.d.R. nicht) wie hier eine
Ansteuerung für eine Kamera zu entwerfen :-) - wenn ich das denn könnte
:-)
Huhu,
also ich lebe noch und meine Abschlussarbeit läuft auf Hochturen.
Um hier mal ein Datum zu nennen, aller aller spätestens ab dem 11.7. bin
ich wieder zu 100% dabei, weil am 10.7. meine Verteidigung sein wird.
Nein, ich strebe aktuell "noch" ;-) nicht den Doktortitel an sondern
begnüge mich erst einmal mit einem Masterabschluss.
Ich hoffe aber, dass ich noch vor Juli die Zeit finde hier weiter zu
machen :)
stay tuned!
lg. David
So meine lieben Freunde,
ich befinde mich im Endspurt und in zwei Wochen ist alles vorbei.
Ich hoffe Ihr habt eure Boards nicht verstauben lassen und steigt mit
mir wieder so begeistert ein, wie wir aufgehört haben.
bis dahin!
Sonnige Grüße
David
Hallo David,
eins muss man Dir lassen: Du hast wirklich Ausdauer und Biss - find' ich
gut.
Wenn's hier weitergeht, werde ich wieder sporadisch mitmachen - je nach
Zeitkontingent.
Allerdings ist es dieses Jahr auch ein wunderschöner Sommer - da möchte
ich nicht zu viel vor dem Rechner hocken. Will sagen: schau'n wir mal.
Für Deine Prüfung in 2 Wochen wünsche ich Dir jedenfalls viel Glück
(obwohl Du das nicht benötigen wirst, denn nach Deinem Schreibstil und
nach Deiner Programmierung zu urteilen, gehörst Du sowieso zu den
helleren Köpfen.)
Viele Grüße
Igel1
Soooo nachdem nun alles vollbracht ist wollte ich mich heute endlich
wieder meinem Hobby zuwenden :)
Also habe ich mir gemütlich eine Tasse Kaffe gemacht und die Box mit
meinem Elektronik-Kram herausgeholt. Der erste Griff ging natürlich zu
der Kamera, die mir dann promt aus der Hand gerutscht ist und exakt in
der vollen Kaffetasse untergegangen ist....
Ein Traumstart quasi....
jetzt liegt sie im Salz zum trocknen und ich hoffe, dass - wenn ich sie
dann morgen einmal anschmeiße - noch alles funktioniert. Sonst muss ich
mir wohl oder übel eine neue bestellen.
Der erste Projekt-Wiederaufnahme-Post muss also doch noch etwas
warten...
schade...
In diesem Sinne :D
bis die Tage
lg.
David
Hallo,
ich schmunzel jetzt etwas, auch wenn es für Dich ärgerlich ist.
Ich bestelle bei recht preiswerten Bastelobjekten meist generell 2
Stück.
Nicht, um für solche Unfälle Reserve zu haben,
sondern nur, weil solche und ähnliche Unfälle nie passieren, wenn man
Reserve liegen hat...
PS: von dieser Kamera habe ich nur eine, ich werde also wohl auf Kaffe
verzichten, wenn ich den Kram raussuche.
Oder fallen Kameras womöglich auch in Cola-Becher?!?
PS: ich hätte die Optik von der Leiterplatte abgeschraubt, den Kram mit
destilliertem Wasser abgespült (notfalls auch einfach unter dem
Wasserhahn) und ausgiebig trocken geföhnt. In die Optik selbst dürfte
nichts eingedrungen sein, wenn Du sie nicht stundenlang in Kaffe gebadet
hast.
Gruß aus Berlin
Michael
Ich finde ohnehin das wir unser Vorhaben deutlich beschleunigen wenn wir
auf das Modell mit Fifo Speicher wechseln.
Damit können wir auf der einfachen Arduino Plattform bleiben und uns den
Dingen widmen die wichtig sind, als mit irgendwelchen Tricksereien zu
versuchen das ohne ans laufen zu bekommen.
Hallo,
Olli Z. schrieb:> Damit können wir auf der einfachen Arduino Plattform bleiben und uns den> Dingen widmen die wichtig sind, als mit irgendwelchen Tricksereien zu> versuchen das ohne ans laufen zu bekommen.
Auf der Arduino Plattform bin ich hier ohnehin, der ist es egal, ob ich
da Arduino spezielles oder plain C oder eine bunte Mischung von beiden
reinpacke, die compiliert das schon richtig.
direkt gefragt: was ist das Ziel der Geschichte?
Also was will letztlich jeder hier mit der Kamera machen?
Gruß aus Berlin
Michael
Ich dachte das hatten wir doch ein paar hundert Antworten weiter oben
schon geklärt?! :-)
Wir wollten damit natürlich auch ein Biöd übertragen, aber eigentlich
ging es ums Protokoll und die Ansteuerlokig sowie Videoformate.
Olli Z. schrieb:> Ich finde ohnehin das wir unser Vorhaben deutlich beschleunigen wenn wir> auf das Modell mit Fifo Speicher wechseln.> Damit können wir auf der einfachen Arduino Plattform bleiben und uns den> Dingen widmen die wichtig sind, als mit irgendwelchen Tricksereien zu> versuchen das ohne ans laufen zu bekommen.
Das denke ich auch, dann können wir in Ruhe das Bild verarbeiten, an den
PC schicken und dort anzeigen.
Wenn wir den ganzen ablauf dann einmal hinbekommen haben sollten, kann
man sich die option ja offen halten, den Sprung auf die andere Kamera
ohne Fifo zu versuchen.
Damit haben wir dann erstmal nicht das Frequenzproblem richtig?
Eine mit Fifo hab ich mir ja damals auch zu gelegt.
Darf ich euch fragen, wie ihr die Kamera anschließt?
Ich hatte mir bei der Kamera ohne Fifo ein Flachbandkabel mit
Pfostenstecker gemacht.
müsste für die mit Fifo dann heute Abend nochmal ein neues machen oder
habt ihr da bessere Lösungen?
Ich habe auch noch eine mit Fifo, dann bleiben wir erstmal dabei! :-)
Für Versuchsaufbauten finde ich ja Dupont-Stifte praktisch. Daher würde
ich, falls nicht bereits vorhanden, an die Platine der Kamera eine
Stiftleiste löten (am besten nach hinten gerichtet damit die Kabel
später nicht vor der Linse rumlammern) und dann mit Buchse/Stecker
Dupont-Wires aufs Steckbrett verbinden.
Hallo,
Olli Z. schrieb:> Ich dachte das hatten wir doch ein paar hundert Antworten weiter oben> schon geklärt?! :-)> Wir wollten damit natürlich auch ein Biöd übertragen, aber eigentlich> ging es ums Protokoll und die Ansteuerlokig sowie Videoformate.
meine Frage deshalb: die Kamera kann 640x480 als Auflösung.
Mit einem AVR sind, egal, ob mit oder ohne FiFo alle paar Sekunden ein
Bild möglich. Das sind bei 16Bit unkomprimiert also 600kB pro Bild wenn
ich mich nicht verrechet habe.
Wir reden also von einem Bild alle 2-3s (mit FIFO) oder alle 15s ohne
FIFO.
Als JPEG dürfte ein Bild um die 30-50kB sind (ist betwas das, was meine
alte DC3840 packt).
Wenn Arduino auch z.B. der ESP32 ist, sind ca. 6-10 Bilder/s direkt auf
einem angeschlossenen Display machbar,
Als "Sucher" für einen "Fotoapparat" gerade noch nutzbar, ein solches
Projekt liegt irgendwo in Netz.
Für mich wäre also eine denkbare Anwendung z.B. alle paar Minuten eine
Wetteraufnahme per WLAN in mein FHEM zu schicken. Da würde ich ohnehin
dann einen ESP32 nehmen. Das ginge prinzipiell auch mit einem AVR und
LAN-IC dran, hier liegt sicher noch ein ENC28J60 rum...
Meine Frage ging also eher in Richtung: was könnte für Euch eine
mögliche Anwendung in dem Umfeld sein?
Gruß aus Berlin
Michael
Hallo,
Olli Z. schrieb:> Also ich, für meinen Teil, habe und brauche keine konkrete Anwendung und> sehe die Sache rein akademisch :-)
ok, dann sehen wir es genauso. Ich frage nachher mal meinen Bekannten,
ob er die mit FIFO hat, dann lege ich die erstmal neben meine ohne. ;-)
Seine liegt nähmlich auch nur sehr akademisch rum...
Aber: haben ist besser als brauchen!
Gruß aus Berlin
Michael
Das freut mich und ich hoffe, dass dein Bekannter die Kamera entbehren
kann :)
Ich denke wir sind uns alle einig, dass dieses Projekt nur dem
Selbststudium (in meinem Fall) oder dem Auffrischen von vorhandenem
Wissen (evtl. in eurem Fall) dienen soll.
Ich bin für meinen Teil schon Glücklich wenn ich ein Foto mit der Kamera
schießen und darstellen kann ;-)
Ich kenne mich mit FIFOs nicht wirklich aus. Das Grundprinzip ist zwar
klar, aber ich werde mich erstmal einlesen müssen.
Zunächst sollten wir aber kurz abklären, dass wir alle mit den selben
Werkzeugen arbeiten :-)
Auf meiner Kamera ist ein AL422B Frame-Buffer Fifo verbaut. Ist das der
gängige, der ebenfalls bei euch bestückt ist?
Angehängt habe ich euch mal das Pinlayout, dass bei mir per Stiftleiste
zum kontaktieren bereit steht.
PCLK und XCLK scheinen weggefallen zu sein, dafür kommen weitere sechs
Pins dazu (vermutlich zur Steuerung/Auslesen des Fifos)
Ich hoffe bei euch sieht es ähnlich aus.
liebe Grüße David
EDIT:
Bei genauerer Betrachtung habe ich gerade festgestellt, dass neben dem
FIFO ebenfalls noch ein Quarz verbaut ist, was auch erklären würde,
warum wir keine XCLK mehr einspeisen müssen.
@David D.:
Musste herzlich über Deinen Kaffeetassen-Absturzbericht lachen - das
hast Du wirklich köstlich beschrieben.
Was die FiFo-Geschichte angeht, so habe ich neben 2x OV7670 hier auch
irgendwo eine OV7670 mit FiFo rumfliegen. Wenn die Zeit bei mir also
ausreicht, so könnte ich auch ein bißchen mitspielen (vermutlich aber
nicht vor Ende August).
Muss allerdings gestehen, dass mich die FiFo-Geschichte wenig reizt, da
sie kaum anspruchsvoll sein dürfte und noch viel weniger zu meinem
eigenen Zielszenario passt (es lautet: mit einem STM32 passable Bilder
aus der FiFo-losen OV7670 herausfischen, dann jpeg-komprimieren und an
einen ESP8266 zum Versand als Email-Attachment übergeben - denn meine
Mäusefalle soll irgendwann an Ihren Besitzer Bilder von dem/den Insassen
schicken).
Wenn's allerdings nur darauf ankommt, ein paar Bilder mit einem atmega
aus einer OV7670 zu ziehen, so dürfte die FiFo-Version wegen nicht
vorhandener Timing-Probleme ca. 100x einfacher auszulesen sein als die
Non-FiFo-Version.
Nevertheless: die FiFo-Version bietet sicherlich eine gute Gelegenheit,
sich in endlicher Zeit ein schönes Erfolgserlebnis durch erste
ausgelesene Bilder zu verschaffen. Und danach kannst Du ja immer noch
auf den STM32 mit Non-FiFo umsteigen :-)
Viele Grüße und Kaffee ahoi
Igel1
Hallo,
Andreas S. schrieb:> Wenn's allerdings nur darauf ankommt, ein paar Bilder mit einem atmega> aus einer OV7670 zu ziehen, so dürfte die FiFo-Version wegen nicht> vorhandener Timing-Probleme ca. 100x einfacher auszulesen sein als die> Non-FiFo-Version.
reivoll wäre, das auf einem ESP32 komplett zu realisieren.
Ob jemand schon einen (einfachen?) JPEG-Encoder auf dem ESP32 compiliert
hat, weiß ich nicht. SPI-PS-RAM kann man beim ESP32 direkt einbinden, es
gibt auch Module, wo schon welcher drauf ist.
Machbar müßte es sein, auch ohne FIFO.
Gruß aus Berlin
Michael
Hallo,
jpeg Decoder auf dem ESP32 ist verfügbar und macht seinen Job.
Gibt ein paar Einschränkungen bei der Ausgabeskalierung, nur
ganzzahligen Teiler usw., für eine Displayanzeige aber kein wirkliches
Problem.
Encoder habe ich noch nichts gesehen.
Ich denke, man wird sich da sicher etwas beschränken müssen bei
Formaten/Profilen oder so. Habe mich mit JPG-Encoding noch nie selbst
befasst.
Gruß aus Berlin
Michael
Guten Abend,
ja es ist ruhig geworden, aber ich denke, dass können wir alle auf die
klimatischen Bedingungen zurückführen, die seit einigen Wochen in ganz
Deutschland herrschen.
Ich genieße derzeit die Sonne und freue mich schon auf die verregneten
kühleren Tagen, an denen man erträglich die Projektarbeit wieder
aufnehmen kann :)
lg.
David
Liebe Urlauber,
ich wende mich an euch mit einer Verzweiflungstat ;-)
Ich habe in den vergangenen Tagen intensiv versucht, den OV7670 mit Fifo
über das TWI anzusteuern.
Das Ergebnis kann ich nicht ganz einordnen. Zunächst hat es nach dem
Equipment Aufbau und erstem Test auf Anhieb funktioniert. ich konnte die
Device ID mit 0x76 0x73 auf den Adressen 0x0A und 0x0B auslesen. Auf
Anhieb! Damit war die Motivation gegeben Großes zu leisten.
Einziges Manko: eigentlich werden diese 2 Read Befehle in der
Endlosschleife ausgeführt. Bei mir stoppt diese aber nach einfachem
Durchlauf. Die Überprüfung mit dem Oszi zeigte mir, dass die SDA Leitung
auf Low verbleibt und nicht wie vorgesehen zum Ende einer Kommunikation
wieder auf High gezogen wird.
Nach etlichen Code Veränderungen und Stecküberprüfungen bis mitten in
die Nacht hatte ich immer noch keinen brauchbaren Ansatz. Verschenkte
aber weitere 3 Stunden in der Fehlersuche, in dem ich zunächst unbemerkt
bei den genannten Stecküberprüfungen ein Kabel falsch zurücksteckte...
no Comment! (Schieben wir es auf die Müdigkeit)
das Studium etlicher Webseiten und allen möglichen Variationen konnte
mir keinen Erfolg bescheren. Der aktuellste Stand ist, dass manchmal die
Kommunikation zu funktionieren scheint und manchmal nicht. Klingt für
mich zunächst nach etwas Undefiniertem - ich kann es aber nicht finden.
Zum Schluss hat mich ein Satz im Datenblatt des SCCB besonders
irritiert: Sinngemäß lautete dieser, dass während des Don't care bits
(Was beim TWI dem ACK/NACK Bit entspricht) der Master sicherstellen
muss, dass der Bus auf LOW gezogen wird.
Diese Einstellung kann ich aber beim TWI Interface gar nicht
beeinflussen, weil dieser ja den Pin auf Eingang Schaltet, um das ACK zu
identifizieren?
Meine aktuelle Theorie lautet also, dass entstehende High Signale beim
ACK den Bus ins straucheln bringen. Sehr Schwammige Aussage und ich
erwarte von euch eine bessere Erklärung. Der Code ist angehängt.
Ich habe mich dann eben wieder entschieden mein selbstgeschustertes
BitBangig auszugraben und siehe da, alles funktioniert wie gewünscht.
Dennoch erinnere ich mich an die Kritik von euch, unter anderem was die
OpenDrain Beschaltung angeht.
Daher hoffe ich, dass ihr meinen Fehler im TWI Bereich findet und wir
das Ding ans laufen kriegen. Offensichtlich gibt es genug, die das mit
der Arduino Lib WIre.Beginn ganz simple hinbekommen....
David D. schrieb:> Diese Einstellung kann ich aber beim TWI Interface gar nicht> beeinflussen, weil dieser ja den Pin auf Eingang Schaltet, um das ACK zu> identifizieren?
Vielleicht kannst Du dafür noch einen Pin opfern und im richtigen Moment
die Leitung mit 100 Ohm (o.ä.) auf low ziehen.
> Ich habe mich dann eben wieder entschieden mein selbstgeschustertes> BitBangig auszugraben und siehe da, alles funktioniert wie gewünscht.
Dann würde ich das so lassen. Wenn kein regelkonformes I2C verwendet
wird, kann man eben die Hardwareunterstützung des Controllers nicht
verwenden...
Hallo Tim, vielen Dank für Deinen Beitrag.
Den Pin im richtigen Moment auf Low zu schalten halte ich für sehr
kompliziert. Da müsste ich ja mit einem Timer den Zeitpunkt abzielen,
der ja von der Frequenz der Übertragung abhängt.
lg. David
Hallo,
da es ja hier recht ruhig geworden ist und die Zeit ohnehin weitergeht:
ich habe mir mal das M5Stack Cam Modul bestellt:
https://www.amazon.de/MakerHawk-M5Stack-Antenna-Arduino-Raspberry/dp/B07F2DNX6M
Die Demosource von github:
https://github.com/igrr/esp32-cam-demo
habe ich mit großer Mithilfe meines Bekannten inzwischen nicht schön
aber lauffähig in die ArduinoIDE geworfen.
Ich fand das als Spielerei interessant, die Kamera ist durchaus
brauchbar, max. 1600x1200 Pixel und kann auch JPEG ausgeben.
Bild gibt es morgen...
Gruß aus Berlin
Michael
Hallo,
Andreas S. schrieb:> @Michael U.:> Dient der USB-C-Anschluß zur Stromversorgung?
ist natürlich auch COM für den ESP32.
> Wie hast Du die Kamera mit Deinem Board verbunden?
Das ist Kamera + ESP32-Board + Akkumöglichkeit + lade-IC usw.
> Und musstet Ihr viele Klimmzüge machen, bis das Teil lief?
An USB stecken, mit dem AP des ESP32 verbinden, Webseite aufrufen,
Bilder anschauen...
> Gibt es Vorteile, die Dein Modul gegenüber den 8$-Varianten> von Aliexpress hat?
Erklärt sich mit obigen von selbst, Kamera-Modul + ESP32-Modul +
USB-Adapter + Akku-Lade-IC.
Soweit die Theorie.
Ich habe das Modul als Spielerei bestellt, kein Drahtverhau, einfach mit
der Software experimentieren.
Nun die Praxis: in der Lieferung war ein Mini-Kühlkörper ohne jegelichen
Hinweis, taucht auch in keiner Beschreibung auf.
Der ESP32 kann ja durchaus merklich warm werden, wenn wie hier
durchgehend WLAN-Traffic gemacht wird. Stört den auch nicht. Hier gab es
nach relativ kurzer Zeit fehlerhafte Bilder, hängende Übertragung usw.
Mit dem Kühlkörper ging es seltsamerweise, leider auch nur etwas länger
bis zu den Fehlern.
Im M5Stack-Forum habe ich dann einen Hinweis gefunden: die Jungs haben
als PullUp am SCCB-Bus nur die internen des ESP32 genommen. Die sind
aber eigentlich sowieso viel zu hochohmig für I2C/SCCB, auch bei nur
einem Slave und kurzen Leitungen. Wenn der ESP warm wird, werden sie
vermutlich noch hochohmiger und es hagelt IO/Fehler.
Der Poster dort im Forum hat PullUps mit 4,7k nachgerüstet und die
Probleme waren weg.
Kann ich mit leben, nur ist die einzige zugängliche Stelle die Lötseite
des Kamera-Steckverbinders und die hat Rastermaß irgendwo um 0,x mm...
Das freut mich auf meine "alten Tage", werde nachher mal schauen, dünne
Litzenadern an Pin 3,5 und 11 des Verbinders zu löten und daran 2
SMD-Widerstände.
Das Bild ist ein nur beim Experimetieren mal gespeichert,
Original-Firmware, 800x600 (kann man dort erstmal nicht verändern),
JPEG-Kompression unbekannt.
Mal schauen, was mein Bekannter heute meldet, der hat seine gestern
abgeholt.
Gruß aus Berlin
Michael
Guten Abend!
da sind mir eure Antworten entgangen. Da scheine ich die E-Mail
Notifikation verpasst zu haben.
Ich wollte die Tage schon einen Post verfassen, bin aber dann doch nicht
dazu gekommen. Ich habe die letzten Wochen nicht geruht und habe einiges
hinbekommen (aber noch kein Bild ;-) )
morgen dann mehr...
machen wir es wie die Politiker in der Abgasaffaire :D
lg. David
Hallo,
zur M5Stack Cam: ich hatte am 22.09. nich 2 Stück bei ebay in China
bestellt
https://www.ebay.de/itm/M5Stack-ESP32-Camera-Module-Development-Board-3D-Wifi-Antenna-Mini-Camera-Board-/173386455615
keine Ahnung, ob es der gleiche Händler ist.
Zumindest kamen die Kameras bereits am 02.10. bei mir an.
Das Problem zum SCCB-Bus tritt auch bei diesen Modulen auf. Mein
BEkannter hat inzwischen PullUps nachgerüstet, ich muß mir da bei 0,6mm
Pitch am Steckverbinder noch was einfallen lassen. Oder einfach meinen
Bekannten damit beschäftigen...
Mit der Änderung läuft das Modul absolut stabil, auch stundenlang zum
Beobachten seines 3D-Druckers beim Drucken.
Wenn man bedenkt, daß das OV2640 Modul nur mit Adapterplatine sowieso
schon für knapp 10€ angeboten wird, diskutiere ich lieber mit der
Software der M5Stack Cam rum.
Die Kamera bekommt man zwar einzeln für rund 3.50€ aus China oder bei
Amazon, nur was soll ich dann mit einer 24-pol. SMD-Buchse mit 0,6mm
Kontaktabstand anfangen?!?
So, jetzt erstmal was sinnvolles machen...
Gruß aus Berlin
Michael
Guten Morgen,
... doch wieder zwei Tage verspätet aber dafür mit einem ausführlichen
Bericht.
Was bisher geschah:
Wie meinem letzten, thematischen Post zu entnehmen, habe ich von der
I2C-Variante zurück auf die eigene Bit-Banging Variante gewechselt und
hatte damit Erfolg, eine Kommunikation aufbauen zu können.
Als nächstes musste ich mir Gedanken machen, wie der FIFO ausgelesen
werden kann.
Bild aufnehmen:
Dafür setze ich den write pointer zurück, warte auf ein VSync Signal,
setzte den Write Enable Pin und warte auf die nächste Flanke bei VSync.
Dann deaktiviere ich Write Enable wieder.
An dieser Stelle sollte das Bild jetzt vollständig im FIFO liegen.
Auslesen:
Ich habe eine Funktion erstellt mit drei Input Parametern: Auflösung y
Richtung, Auflösung x Richtung und Bytes Per Pixel. In dieser
Reihenfolge sind die drei Parameter in For-Schleifen verschachtelt. In
der innersten lese ich das anstehende 8Bit Signal aus und Clock den
Read-Pointer.
das ausgelesene parallele 8 Bit Signal setzte ich zu einem Byte zusammen
und übertrage es per Uart an den PC.
Wie aber gehe ich mit den Daten am PC um? Die ersten Versuche waren
logischerweise mit einem fertigen Terminal Programm. Nachdem ich es aber
geschafft habe, nicht nur FF oder 00 für jedes Byte zurückzubekommen,
konnte ich mit der Vielzahl an Bytes nicht mehr umgehen. Also habe ich
mich daran gemacht mit dem visual Studio ein eigenes „Terminal“ für den
OV7670 zu schreiben. Da ich auch hier wieder viel lernen muss, zieht
sich diese Arbeit etwas hin, besonders was die Verarbeitung von
eingehenden Datenströmen angeht.
Aber, ich habe es geschafft, die Daten, die am fertigen Terminal
ankommen, zu kopieren und als eine CSV Datei zu speichern. Diese Datei
kann ich mit meinem Programm als ein Bild einlesen. Aktuell bekomme ich
da aber nur ein „Fehler Bild“ was meiner Meinung nach, nach einem nicht
vollgeschriebenen Fifo oder anderen Fehlern aussieht. (Siehe Anhang).
Aktuell versuche ich den eingehenden Daten stream direkt mit meinem
Programm verarbeiten zu können.
Das ist also mein Stand. Bei Interesse gehe ich auch gerne tiefer ins
Detail.
Ich vermisse den Olli noch in unserer kleinen Runde ?
Das Board sieht schick aus. Vlt. Werde ich auch darauf mal zurückkommen,
sobald mein OV läuft ?
aber wie schon des Öfteren diskutiert werde ich zunächst bei Arduino
bleiben und ggf. später einmal den ESP ausprobieren.
lg. und ein schönes Wochenende
David
Hallo,
vielleicht hätte ich mir doch von meinem Bekannten die OV760 mit FiFo
mitnehmen sollen? Naja, kann ich am nächsten Freitag ja noch machen...
Einerseits finde ich Deine Ausdauer gut, ich bin im Moment aber etwas
hin- und hergerissen...
Was für ein Bildformat liest Du von der kamera in den Fifo ein?
Der kann von der Größe nicht alle Formate und Größen und die Effekte,
die sich dann ergeben, sind lustig, wie mein Bekannter feststellen
mußte.
Den Bildern hätte ich einen passenden BMP-Header verpsst, der ist
überschaubar auch auf dem AVR gemacht, und eben vor den Daten
rausgeschickt.
Eingelesen hätte ich "old school" mit altem TeraTerm in den Log-Buffer
aund dann als .bmp gespeichert und angezeigt.
Wahlweise das File in einen Hex-Editor geworfen und geschaut, was ich
mir da für Müll geschickt habe.
Ich habe soviel Extra-drumrum auch schon programmiert, bei meinem
LogicAnalyzer z.B. in VB6. Aber erst, nachdem die empfangenen Rohdaten
ok waren und es um die Anwendung ging.
Ich bin durchaus noch interessiert hier mitzuspielen. Macht dann aber
für mich nur Sinn, wenn ich einen Source durch den Compiler schicken
kann und flashen und dann mir die Ergebnisse anschauen kann. Das mache
ich gern auch mit Rohdaten ohne header usw, dann muß aber eindeutig
sein, was ankommen soll, Format, Auflösung usw.
Sonst ist es zuviel stochern im Nebel für mich, wenn ich mir erst aus
den Cam-Inits und den Loops im Source zusammenreimen soll, was
rauskommen müßte. Ist ja auch eine Zeitfrage.
David D. schrieb:> Das Board sieht schick aus. Vlt. Werde ich auch darauf mal zurückkommen,> sobald mein OV läuft ?> aber wie schon des Öfteren diskutiert werde ich zunächst bei Arduino> bleiben und ggf. später einmal den ESP ausprobieren.
Ich sage es jetzt mal so: ist auch Spaß an der Freude. Ich darf meine
teilweise recht bescheidenen C/C++ Kenntnisse stark aufbessern, um mich
mit den Espressiv Demo-Source auseinanderzusetzen. Ich darf mit mit den
Modi und dem Datenblatt der OV2640 auseinandersetzen, mit der
Problematik, das die Jungs nicht nur den Hardware-Design-Fehler drin
haben (mein Bekannter darf jetzt löten...) sondern dem Modul nicht auch
noch einen PSRAM spendiert haben. Der ESP32 kann nur 128k im Stück
reservieren, damit ist bei 800x600 JPG Ende. Ich würde aber gern die
volle Auflösung 1600x1200 als Einzelbild übertragen bekommen.
Wehalb ich das mache? Ich könnte die Cam z.B. auf das rumliegende 20€
"Roboter"-Fahrgestell kleben, 640x480 mit 20-30 Frames/s sind dafür
ausreichend und auf Knopfruck ein Standbild in voller Auflösung wäre
gut.
Hat auch alles keinen wirklichen Nährwert...
Die Kombination OV7670 mit Mega328 hat da null Chance.
OV7660 mit ESP8266, besser ESP32 würde da noch machbar sein.
Gruß aus Berlin
Michael
Hallo,
auch wenn es etwas am Thema vorbeigeht:
ich hatte mir noch ein OV2640 Modul bestellt
https://eckstein-shop.de/OV2640-Camera-Board
mit kurzen Dopont-kabeln an ein ESP32 DevKit gesteckt und...
Kameratyp nicht erkannt -> reset ist auf dem Modul nicht mit dem Pin
verbunden sondern mit 0-ohm Brücke an einer R/C-Resetschaltung.
Dem Cam-modul gefiel es offenbar nicht, daß der ESP32 XCLK erst recht
spät nach PowerOn erzeugte. Die Camera braucht aber XCLK auch z.B. für
SCCB.
Also umgelötet und der Kameratyp wurde richtig erkannt.
Kamera war jetzt auch im Netz, das ankommende JPED aber laut Browser
nicht dekodierbar. Nach einigem kramen in den Sourcen beschlossen, XCLK
von 20MHz auf 10MHz runtergesetzt und jetzt gab es auch Bild.
Das Modul ist also recht sensibel am Bus mit den 10cm Leitungen...
Letztlich ist es mit 8MHz XCLK absolut stabil.
Mit der Erkenntnis ein originales M5Stack CAM Modul so geflasht und...
stabil, keine Aussetzer oder Bildehler mehr auch ohne nachgerüstete I2C
PullUp Widerstände. Hier scheinen sich wirklich alle Toleranzen nach
Murphy zu treffen, mit den Widerständen gehen auch die 20MHz XCLK, aber
auch gerade noch so, wie mein Bekannter bei einer Kamera bemerkt hat.
Das als Tipp, falls ich jemand das M5Stack CAM kaufen sollte. Das in die
ArduinoIDE verpackte cam-demo von github schicke ich dann gern per Mail
zu, ich will es hier nicht reinstellen, weil es sich nicht mit allen
IDF-Versionen lauffähig compilieren läßt. Mit der ESP32
Boardmanager-Version 1.0.0 geht es auf jeden Fall erstmal.
Gruß aus Berlin
Michael
Michael U. schrieb:> reset ist auf dem Modul nicht mit dem Pin> verbunden sondern mit 0-ohm Brücke an einer R/C-Resetschaltung.> Dem Cam-modul gefiel es offenbar nicht, daß der ESP32 XCLK erst recht> spät nach PowerOn erzeugte. Die Camera braucht aber XCLK auch z.B. für> SCCB.> Also umgelötet und der Kameratyp wurde richtig erkannt.
Könntest Du das bitte etwas näher erklären?
Hast Du die R/C-Resetschaltung vom Reset-Pin der Kamera getrennt
und separat herausgeführt und dann separat von Deinem ESP32
den Reset angestoßen nachdem XCKL stabil war ?
> Kamera war jetzt auch im Netz, das ankommende JPED aber laut Browser> nicht dekodierbar. Nach einigem kramen in den Sourcen beschlossen, XCLK> von 20MHz auf 10MHz runtergesetzt und jetzt gab es auch Bild.
Wie hast Du das Bild ausgewertet?
Hast Du es zunächst in Deinen Computer übertragen? (wenn ja: wie?)
> Das Modul ist also recht sensibel am Bus mit den 10cm Leitungen...> Letztlich ist es mit 8MHz XCLK absolut stabil.
Welche Frameraten erreicht man damit?
> Mit der Erkenntnis ein originales M5Stack CAM Modul so geflasht und...> stabil, keine Aussetzer oder Bildehler mehr auch ohne nachgerüstete I2C> PullUp Widerstände. Hier scheinen sich wirklich alle Toleranzen nach> Murphy zu treffen, mit den Widerständen gehen auch die 20MHz XCLK, aber> auch gerade noch so, wie mein Bekannter bei einer Kamera bemerkt hat.
Interessant. Danke für die Hinweise.
> Das als Tipp, falls ich jemand das M5Stack CAM kaufen sollte. Das in die> ArduinoIDE verpackte cam-demo von github schicke ich dann gern per Mail> zu, ich will es hier nicht reinstellen, weil es sich nicht mit allen> IDF-Versionen lauffähig compilieren läßt.
Bitte erkläre einem Arduino-Gelegenheitsuser noch etwas die Zs.hänge:
Du installierst den Board Manager für ESP32 - das habe ich verstanden.
Dann wählst Du Dein ESP32-Board aus (by the way: welches hast Du?).
Und wie integrierst Du dann die cam-demo von github?
(bitte poste einmal den Link zu dem cam-demo github-Projekt)
Muss man dann zunächst die cam-demo in der ESP-IDF compilieren,
um sie anschließend in Arduino als Library irgendwie importieren/
integrieren zu können?
> Mit der ESP32> Boardmanager-Version 1.0.0 geht es auf jeden Fall erstmal.
Viele Grüße
Andreas
Hallo,
Andreas S. schrieb:> Hast Du die R/C-Resetschaltung vom Reset-Pin der Kamera getrennt> und separat herausgeführt und dann separat von Deinem ESP32> den Reset angestoßen nachdem XCKL stabil war ?
Es geht um dieses Modul:
https://eckstein-shop.de/OV2640-Camera-Board
Auf der Rückseite sind an der Unterkannte einige 0-Ohm Brücken, die
festlegen, ob PowerOn und Reset auf die Stiftleite gehen oder intern
passend belegt werden.
Im Lieferzustand sind die beiden Signale nicht mit den Pins verbunden...
Hinweise dazu gibt es (natürlich) keine, man findet aber den Schaltplan
im Netz und kann es dann selber überprüfen.
Ich mache da gern mal ein Bild der Rückseite mit Beschriftung der
zuständigen Lötpunkte wenn jemand auch genau diese Kamera Modul-Version
hat.
Zum Rest: ja, die Software erzeugt einen Restimpuls nachdem sie XCLK
eingerichtet hat. Der nutze nur nicht viel, weil eben der Reset-Pin beim
Modul nicht angeschlossen war.
>> Kamera war jetzt auch im Netz, das ankommende JPED aber laut Browser>> nicht dekodierbar. Nach einigem kramen in den Sourcen beschlossen, XCLK>> von 20MHz auf 10MHz runtergesetzt und jetzt gab es auch Bild.>> Wie hast Du das Bild ausgewertet?> Hast Du es zunächst in Deinen Computer übertragen? (wenn ja: wie?)
Ich habe das fertige Demo von Espressif:
https://github.com/m5stack/esp32-cam-demo
Die Anpassungen, damit es sich aus der ArduionIDE compilieren läßt, hat
mein Bekannter gemacht. Ich will die Sketch-Version hier nicht anhängen,
weil sie eben nur eine Spielwiese ist, ich sende sie aber gern per Mail.
> Welche Frameraten erreicht man damit?
Real bei 800x600 ca. 3 Frames/s, ich habe muß mich erstmal mit der
Software auseinandersetzen...
> Bitte erkläre einem Arduino-Gelegenheitsuser noch etwas die Zs.hänge:> Du installierst den Board Manager für ESP32 - das habe ich verstanden.> Dann wählst Du Dein ESP32-Board aus (by the way: welches hast Du?).
Richtig. Im Moment hängt sie an so einem ESP32 Modul im NodeMCu-Format,
prinzipiell ist es aber eigentlich egal, als Beispiel:
https://www.amazon.de/ELEGIANT-ESP32-ESP32-DEVKITC-genuine-ESP-WROOM-32/dp/B06XWVS2SJ> Und wie integrierst Du dann die cam-demo von github?> (bitte poste einmal den Link zu dem cam-demo github-Projekt)> Muss man dann zunächst die cam-demo in der ESP-IDF compilieren,> um sie anschließend in Arduino als Library irgendwie importieren/> integrieren zu können?
Nein, Sketchordner ESP32-Cam anlegen, alle Dateien des Demos in den
Sketchordner, den Webserver noch dazu (liegt auch bei github). Dann die
main.c in ESP32-Cam.ino umbenennen damit die ArduinoIDE zufrieden ist.
Es hagelt diverse Fehlermeldungen weil normalerweise im ESP-IDF einige
Infos beim Compile abgefraht werden.
Den Kram hat mein Bekannter und ich passend nachgetragen, die "fertige"
Version kann ich Dir, wie gesagt, per Mail zusenden.
Das Projekt geht ohne Änderungen auch auf der M5Stack Cam:
https://www.amazon.de/MakerHawk-M5Stack-Antenna-Arduino-Raspberry/dp/B07F2DNX6M/ref=sr_1_1?s=computers&ie=UTF8&qid=1539026864&sr=1-1&keywords=m5stack+cam
Gruß aus Berlin
Michael
@Michael:
Danke für Deine Infos!
Toll, dass Ihr dies alles ans Fliegen bekommen habt.
Mir juckt es dabei arg in den Fingern - aber es hilft alles nichts:
Als 120% Berufstätiger habe ich aktuell schlicht nicht genügend Zeit
fürs Basteln und muss mich daher mit Kopfkino begnügen ...
Allerdings: für Letzteres hast Du einen guten Film gedreht :-)
Danke nochmals für Deine Erklär-Mühen.
Viele Grüße
Igel1
Guten Abend/Nacht,
Die Kommunikation ist vorhanden! Wie erwähnt bastel ich grade an meinem
kleinen Terminal PRogramm, dass in naher Zukunft auch die Bilder
darstellen können sollte.
Heute ist mir der Durchbruch gelungen, nachdem ich Tage damit verbracht
habe meinen Kenntnisstand um Themen wie Events, Delegaten und Threading
in C# zu erweitern.
Herausbekommen ist folgendes:
Ich kann die einzelnen Register vom PC aus lesen.
Aufgabe für morgen ist es, die Register vom PC aus schreiben zu können.
Um sich das dauernde Flashen des uController zu sparen, wenn man nur
kleine Änderungen ausprobieren möchte.
Anbei ein Screenshot zum aktuellen "Roh-Modell"
lg. David
Hallo David,
das sieht klasse aus!
Da viele Register schlecht oder gar nicht dokumentiert sind, hätte man
mit Deinem Tool eine gute Möglichkeit, die Auswirkungen von Änderungen
der Parameter in den OV7670-Registern ohne lange Turn-Around-Zeiten, zu
testen.
Wirst Du den Code frei verfügbar machen? (z.B. auf GitHub?)
Viele Grüße
Igel1
Hallo,
Deine Ausdauer ist lobenswert, die Kenntnisse in C# zu erweitern auch.
Beruflich ist sowas mit Sicherheit ein Vorteil, für als inzwischen
Rentner eher weniger. Mir reicht es, meine C/C++-Kenntnisse irgendwie
auszubauen, fürher gab es auf µP und µC für mich nur ASM..
Daher mehr ein paar allgemeine Gedanken auch an Andreas S.:
Datenblätter sind selten Romane, das waren sie auch früher schon nicht
und die Zusammenhänge zusammenzusuchen ist mühsam und kostet Zeit.
Er innert mich an meine erste größere Übung, am C64 den SAA52xx
Videotextdecoder in Gang zu bringen. Datenblatt war verfügbar,
Appliaktionshinweise war ziemlich nichts. Mußte ich also auch den Aufbau
von Videotext erstmal verstehen lernen usw. Einzige Kontroll war ein
kommerzielles Programm für den C64, das ich dann teilweise
disassemblieren konnte. Teilweise, weil es nur
"Maschinensprache-Monitore" gab, die eben ab einer Adresse den
Speicherinhalt als ASM-Mnemotics versuchten auszugeben.
Sinn der Vorrede: die OV7670 hat 201 Register. Das Datenbaltt ist
üblich, alles drin. Natürlich muß man dazu Vorkenntnisse haben. Wozu
gibt es VSYNC und HSYNC bei einer zeilenweisen Bilddarstellung, was
bedeuten die Bildformate und wie sind die Daten aufgebaut, ws ist
Farbsättigung, Gamma, digitale Verstärkungsregelung usw. usw.
Das erklärt ein Datenblatt nicht.
Es gibt ein Applikation-Dokument im Netz zur OV7670 bei www.play-zone.ch
Google hat ihn gefunden, ich selbst auf der Seite nicht, deshalb hänge
ich das pdf hier mal frech ran.
Mit einem Tool einfach so an den Registern rumzuspielen wäre für mich
wie
Lottospielen, nur mit schlechteren Gewinnchancen...
Wenn ich die Kamera mit den beispielwerten des Herstellers auf einen
Mode setze, muß hinten das erwarete Bild rauskommen.
Bis ich die Abhängigkeiten nur an Hand des Datenblattes verstanden
hätte, wäre wohl 2020. Ich muß die Grundlagen verstehen, mich auf den
Hersteller verlassen und kann dann natürlich auch mal variieren. Dann,
wenn ein reproduzierbates Ergebnis ankommt, nicht vorher.
Vor allem: all das nutzt nur genau für diesen einen Kamera-Chip.
Ich muß aber verstanden habe, was nötig ist. Ich muß im datenbaltt
suchen können, wie ist der Speicheraufbau, wie werden die Bilddaten
abgelegt, wo lege ich fest, wo im Speicher Start- und Endpunkt einer
Bildzeile ist, wo lege ich fest, wieviele Zeilen mein Bild haben soll
usw.
Wenn ich ein bestimmtes Ausgabeformat haben will, will ich im Datenblatt
schauen und geziehlt suchen können, ob der Chip das kann, wie ich es
einstellen mus, damit er es ausgibt und wie gibt es es aus, 8Bit, 16Bit,
24Bit, 32Bit, BigEndian, LittleEndian usw.
Ist bei der OV2640 mit der ich im Moment etwas rumspiele auch ein Drama:
ein Hersteller beispiel mit den Inits für die Auflösungen wurde
übernommen. Da wurde dann gekürzt und drumrumgeschrieben, weil z.B. mehr
als 800x600 JPG auch auf einem ESP32 wegen der Ramverwaltung (max. 128kB
im Stück verfügbar) nicht gehen. Mit PSRAM dran kann ich mir aber auch
einen 4MB-Buffer holen. Das hat aber soweit ich bisher gefunden
habe,noch keiner wirklich realisiert. Ich will aber wahlweise ein
Standbild in 1600x1200 haben... Die Stream-Demos gegen einen
HTML-JPG-Stream aus, besser wäre aber sehr wahrscheinlich ein
MJPG-Videostream, hat aber wohl auch noch keiner probiert mit dem ESP32
+ PSRAM.
Ist bei OV7670 mit FIFO doch auch ein Problem: der FIFO ist 384kB groß,
ein 640x480 in 16Bit paßt also nur in 2 Halbbildern rein. Als komplettes
Bild gehen nur 480x320.
PS: toller Roman wieder geworden......
Gruß aus Berlin
Michael
Hallo,
Andreas S. schrieb:> Ganz so frech warst Du dann doch nicht - es hing nämlich nichts dran :-)
Stimmt...
Hast recht mit dem play-zone Link, hat sich dann ja jetzt erledigt.
Andreas S. schrieb:> Außerdem haben die Arduino-Anhänger ja diese> Wahnsinns-Compile&Flash-Zeiten (die ich beim STM32 mit J-Link ja nicht> habe). Da macht so ein Register-Tweating-Tool schon irgendwo Sinn.
Das stimmt natürlich schon. Angefangen habe ich ja mit EProms, noch dazu
in der DDR. Da hat man es sich aus gant anderen Gründen gut überlegt, ob
eine Änderung wiklich richtig und sinnvoll war. Löschen und
Programmieren dauerte da merklich länger und außerdem konnte es je nach
Qualität und Herkunft der Eproms schon passieren, daß nach dem 5.
Löschen etliche zellen eben auf 0 bleiben. Vermutlich ist das bei mir
eben auch teilweise Gewohnheit. Heute dann eher, um während compilieren
und flashen schon zu der Erkenntnis zu kommen, daß man da gerade Mist
gebaut hat. Naja, einen Flash bei AVR oder ESP habe ich noch nicht
kaputt bekommen.
Mein Bekannter hat früher auch gern mal einen Linux-Kernel gebaut, da
waren Stunden nicht unüblich zum compilieren.
Gruß aus Berlin
Michael
Andreas S. schrieb:>> Wirst Du den Code frei verfügbar machen? (z.B. auf GitHub?)>
Hallo Zusammen, mein Job nimmt meine Zeit doch mehr in Anspruch als es
noch als Student der Fall war. Zumindest was die flexibilität angeht.
Daher zieht sich mein Vortschritt leider etwas.
Um auf die Frage von Igel zurückzokmmen, ich würde euch den Code oder
das Programm zur Verfügung stellen, sobald es eingermaßen "Bug-Frei"
läuft. Derzeit gibt es noch viele interferenzen die ich noch nicht ganz
überblicke. Ich hoffe an diesem langen Wochenende mich nocheinmal
intensiv mit dem Thema auseinander zu setzten zu können und endlich mal
einen Bildstream auslesen zu können.
viele Grüße
David
David D. schrieb:> Hallo Zusammen, mein Job nimmt meine Zeit doch mehr in Anspruch als es> noch als Student der Fall war.
Ja, definitiv: Arbeit kann einem das ganze Leben versauen ;-)
> Daher zieht sich mein Fortschritt leider etwas. [Zitat mit typofix]
Willkommen im Club.
> Um auf die Frage von Igel zurückzokmmen, ich würde euch den Code oder> das Programm zur Verfügung stellen, sobald es eingermaßen "Bug-Frei"> läuft. Derzeit gibt es noch viele interferenzen die ich noch nicht ganz> überblicke. Ich hoffe an diesem langen Wochenende mich nocheinmal> intensiv mit dem Thema auseinander zu setzten zu können und endlich mal> einen Bildstream auslesen zu können.
Okay - aber lege die Latte Deines Qualitätsanspruchs an Dich selber
lieber nicht zu hoch. Habe schon viele erlebt, die deshalb Ihre Projekte
nie veröffentlicht haben - ich fand das immer schade.
Viele Grüße
Igel1
Hallo,
damit es hier nicht so ausgestorben aussieht... ;)
Stand meiner M5Stack Cam und Odroid Go Viewer:
Läuft prinzipiell stabil.
Prinzipiell: Cam macht QVGA (320x240) als JPG. Odroid Go holt das Bild
im HTML-Rahmen, decodiert das JPG und zeigt es auf dem Display
8ebenfalls 320x240) an. Sind ca. 1,5 Bilder/s, wenn ein Bild auf dem
Display ist, fordert er die Webseite einfach weider an.
Die Idee, jetzt einen "hardware-Zoom" einzubauen: Markierung als Rahmen
auf dem Display, mit dem Kreuzbutton verschiebbar. Dann ein Bild der
Camera in SVGA (800x600) anfordern und den entsprechenden Ausschnitt auf
dem Display anzeigen.
Das geht vorest nur prinzipiell.
Probleme im Viewer: Tastenabfrage lahm, weil der JPG-Decoder relativ
lange pro Block braucht.
Ansonsten klappt die Idee so zumindest erstmal.
Bei der Camera habe ich zumindest soweit in das Cam-Demo reigefasst, daß
ich eine Funktion zum Wechsel der Auflösung "on-the-fly" stabil in Gang
habe. Probleme mit dem Speicher (framebuffer malloc/free führt schnell
zur Fragmentierung und Speichermangel, also Buffer für SVGA einmal
geholt und den behalten) sind soweit geklärt.
Jetzt bekomme ich aber nach dem Wechsel der Auflösung nur noch
"Nachtaufnahmen", offenbar muß ich noch einige andere Einstellungen des
Camera-Chips jeweils passen setzen, das muß ich noch klären...
PS: wenn ich es morgen nicht wieder vergesse bringe ich zumindest mal
die OV7670 mit FIFO von meinem BEkannten mit.
Gruß aus Berlin
Michael