PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : CPU wird langsamer, Fusebits falsch ???



modtronic
27.05.2019, 17:30
Nabend zusammen

Das Problem beschäftigt mich schon eine Weile.
Ich habe mittels AT Mega 32 und 128 eine eigene SPS zur Steuerung meiner Modellbahn gebaut. HIer die unterschiede ja nach geforderter Rechenleistung
Beide laufen mittels Quarz 8 und 16 Mhz.

Hauptsächliche habe ich das Problem wenn ich mit dem I2c Bus arbeite und mehrere Portbausteine anspreche (MCP23017) die CPU merklich langsamer wird.
Das ganze erkennt man, das ein RUn led die ganze Zeit blinkt. Diese wird deutlichen "träger".

Hauptsächlich wirklich dann wenn ich i2c Routinen zb für die Ausgabe programmiere.

Meine Frage ist, ob jemand mal die korrekte Fusebits Einstellung hat für 8 und 16 Mhz Betrieb, im Datenblatt und auch im Netz bin ich nicht wirklich so fündig geworden.
Ich hatte mal gelesen das bei Falscher Taktrate dieses Phenomon eintreten kann.

ich programmiere meine CPus mit PonyProg bzw Übertrage damit meine Programme.

Danke im Voraus
Patrick

shedepe
27.05.2019, 18:10
Wenn deine I2C Routinen entsprechend lange brauchen wird dein Blinken in der Mainloop zwangsläufig langsamer (Der Controller macht ja was anderes). Das hat nichts mit den Fuses zu tun: Zum berechnen der Fuses lohnt sich das Tool hier: http://www.engbedded.com/fusecalc/

oberallgeier
27.05.2019, 18:34
.. mittels AT Mega 32 und 128 eine eigene SPS .. wenn ich mit dem I2c Bus arbeite .. die CPU merklich langsamer wird ..Hallo Patrick,

welche Taktrate hast Du denn beim I²C eingestellt? Und wie groß/lang/umfangreich (so ungefähr wenigstens) sind denn Deine gesendeten/ausgetauschten Datenpakete ?

modtronic
27.05.2019, 22:17
Nabend

Für den i2c Bus verwende ich die Einstellungen von Codevision. das sind soweit ich weiss 100 Khz..aber ich will mich nicht festlegen, muss auch sagen habe mir das meiste selber
erarbeitet daher, wenn es lief war es ok..es gibt bestimmt natürlich bessere wege zum Ziel.

Ich habe für die beiden Ports des MCP23017 eine Additionsroutine geschrieben damit ich jeden einzelnen Pin über eine Interne Variable ansprechen kann.
Diese bIts haben immer die wertigkeit 1,2,4, 8..bis 128 und werden wenn sie beschrieben werden addiert und auf den Port gelegt.
Ich vermute das diese Routine viel Rechenleistung fordert..

Vllt hat hier einer eine andere Idee..wie man sowas lösen kann.
Die Fusebits sind auf jeden Fall korrekt.

Gruss
Patrick

shedepe
28.05.2019, 08:53
Prinzipiell ist es so: Wenn du kein Problem damit hast, dass deine Hauptschleife manchmal langsamer läuft (womit man in der Regel bei der Verwendung von Interrupts oder zeitaufwendigen Unteroutinen rechnen muss), dann ist doch alles in Ordnung.

Ohne deinen Code können wir dir aber auch nicht sagen ob man das effizienter gestalten kann.

modtronic
28.05.2019, 12:35
Hallo

Ja..sagen wir so...es stört schon da ich gerne gewisse Abläufe schneller brauche da unterschiedliche CPUs miteinander arbeiten

Meine Code ist folgender Massen

i2c_start();
i2c_write(adresse des mcp)
i2c_write(0x14) // zb Port A
i2c_write( data1 + data2+ data4 + data8+ data16 + data32 + data64 + data128 );
i2c_stop();

Das benötige ich jetzt so oft wie ich ports habe. jeder mcp23017 hat zwei ports, also pro ic 2x

die variablen data werden mit der jeweiligen wertigkeit geschrieben zb 1 + 2 ergibt eine 3
so kann ich jeden einzelnen Pin einfach ansprechen, und beinflusse je nach variable immer nur den entsprechenden pin des mcp

problem hier ist, um so mehr ich diese routine verwende umso langsamer wird sie.
frage ist nun ob man es vllt einfacher machen kann , da ich auch jede variable deklarieren muss

Grüsse
Patrick

shedepe
28.05.2019, 14:40
Also I2C Frequenz hochsetzen: Das geht auch unabhängig vom Slave CPU Takt. (z.B. auf 400 kHz)
Wie oft rufst du das auf? Und welche i2c library verwendest du?

Und dann zeig mal etwas mehr Code. So sieht man ja echt nichts davon. Wird das in einem Interrupt aufgerufen? Welche Typen sind die Variablen? Also das was lang dauert ist vermutlich die Kommunikation. Da könnte es helfen eine Interrupt basierte Library zu verwenden.

modtronic
28.05.2019, 16:45
Hallo

mehr code gibt es für die ausgabe nicht.
die routinen laufen permantent im programm mit.
Es gibt eine eigangsroutine und eine ausgangsroutine.
die probleme fangen erst an wenn die ausgangsroutinen wie oben gezeigt ins programm eingefügt werden..ca wenn ich das ganze 9 oder 10 mal aufrufe.

die Variablen sind immer data mit der entsprechenden wertigkeit
zb

taste 1
data1 = 1

taste 2
data2 = 2

taste 3
data4 = 4

wenn man das jetzt addiert ensteht die bitkombination

1 + 2 + 4 + 0 + 0+ 0 + 0 +0 = was dann irgendwann 0- 255 entspricht um den mcp port anzussprechen
vllt kann man das auch mit einer routine anders machen

die lib ist die i2c.h von codevision

Grüsse
Patrick

021aet04
28.05.2019, 22:00
Hast du schon versucht das Ergebnis vorher zusammenzusetzten und dieses dann gesamt an die Funktion zu übergeben?
Also in etwa so :

unsigned char ergebnis = data1 + data2 + ... + data8
I2c_start
...
...
...
i2c_write(ergebnis)
I2c_stop

Was du auch testen kannst wäre einen fixen wert zu übergeben (und schauen ob sich etwas verbessert)

Ein weiterer test wäre nicht mit addition sondern mit schieben (ergebnis = (data1<<0) | (data1<<1) | ... | (data8<<7) ).
In dataX steht dann eine 0 oder 1 je nachdem ob der Eingang low oder high ist.

MfG Hannes

shedepe
28.05.2019, 22:07
Kann die Library denn überhaupt den Hardware I2C des Atmegas nutzen. Wenn ich danach google, dann sieht das stark danach aus als ob die lib Software I2C auf jedem beliebigen Pin machen kann. Da muss man sich natürlich nicht wundern wenn das entsprechend langsam ist.

Als alternative kann ich die lib von Peter Fleury empfehlen: http://homepage.hispeed.ch/peterfleury/avr-software.html
Geht dann natürlich nur auf den Hardware I2C Pins.

modtronic
29.05.2019, 11:56
Hast du schon versucht das Ergebnis vorher zusammenzusetzten und dieses dann gesamt an die Funktion zu übergeben?
Also in etwa so :

unsigned char ergebnis = data1 + data2 + ... + data8
I2c_start
...
...
...
i2c_write(ergebnis)
I2c_stop

Was du auch testen kannst wäre einen fixen wert zu übergeben (und schauen ob sich etwas verbessert)

Ein weiterer test wäre nicht mit addition sondern mit schieben (ergebnis = (data1<<0) | (data1<<1) | ... | (data8<<7) ).
In dataX steht dann eine 0 oder 1 je nachdem ob der Eingang low oder high ist.

MfG Hannes

Moin

Das mit dem ergebnis vorher hatte ich auch schon. bewirkt keine änderung.
Was meinst du genau mit schieben ???

grüsse
Patrick

- - - Aktualisiert - - -


Kann die Library denn überhaupt den Hardware I2C des Atmegas nutzen. Wenn ich danach google, dann sieht das stark danach aus als ob die lib Software I2C auf jedem beliebigen Pin machen kann. Da muss man sich natürlich nicht wundern wenn das entsprechend langsam ist.

Als alternative kann ich die lib von Peter Fleury empfehlen: http://homepage.hispeed.ch/peterfleury/avr-software.html
Geht dann natürlich nur auf den Hardware I2C Pins.

Moin

wie gesagt, ich habe vieles selber erlernt und so geht es ja auch.
ob und was die interne lib kann, weiss ich nicht. ich nutze codevision

interessant wäre, mir vllt mit einem beispiel zu zeigen was du genau meinst.
leider habe ich das so nicht ganz verstanden...

Grüsse
Pat

- - - Aktualisiert - - -

gibt es deine keine lib für den mcp23017 ??
habe nur was für den arduino gefunden

Klebwax
29.05.2019, 13:09
i2c_start();
i2c_write(adresse des mcp)
i2c_write(0x14) // zb Port A
i2c_write( data1 + data2+ data4 + data8+ data16 + data32 + data64 + data128 );
i2c_stop();


Die achtfache Addition dürfte bei einem ATMEGA mit 16MHz so rund eine µs dauern. Wenn das versehentlich 16-Bit Variable sind, vielleicht auch zwei. Ist also unerheblich. Die Übertragung mit 100kHz I2C dauert etwa 300µs (3*9 Takte plus Start und Stop), und das unabhängig davon, ob die 100kHz in SW oder in HW gemacht werden. Um das Ganze etwas zu beschleunigen, kann man den "Sequential mode" Mode verwenden (Datenblatt 3.2.1). Da kann man alle 16 Bit in einem I2C Transfer schreiben.

Aber selbst wenn man das zweimal macht, dauert das weniger als eine Millisekunde. Das merkt man nicht, es muß also etwas anderes sein.

MfG Klebwax

021aet04
29.05.2019, 15:25
Was schieben ist bzw wie man schiebt, steht dort. Als Beispiel:
Ergebnis = (1<<2) | (1<<3);
(1<<2) ist ein Schiebebefehl => es wird eine 1 geladen und um 2 stellen nach links geschoben => es steht dann beim 3ten Bit im Ergebnis eine 1

Das Zeichen | bedeutet bitweises Oder

Beim oberen Beispiel hast du dann im Bit 2 und Bit 3 eine 1 stehen.

Ich würde mir die Grundlagen der Digitaltechnik anschauen.

MfG Hannes

modtronic
29.05.2019, 15:30
Die achtfache Addition dürfte bei einem ATMEGA mit 16MHz so rund eine µs dauern. Wenn das versehentlich 16-Bit Variable sind, vielleicht auch zwei. Ist also unerheblich. Die Übertragung mit 100kHz I2C dauert etwa 300µs (3*9 Takte plus Start und Stop), und das unabhängig davon, ob die 100kHz in SW oder in HW gemacht werden. Um das Ganze etwas zu beschleunigen, kann man den "Sequential mode" Mode verwenden (Datenblatt 3.2.1). Da kann man alle 16 Bit in einem I2C Transfer schreiben.

Aber selbst wenn man das zweimal macht, dauert das weniger als eine Millisekunde. Das merkt man nicht, es muß also etwas anderes sein.

MfG Klebwax

Tag

Das es an der Kommunikation des Busses liegt hatte ich auch nicht gedacht
sondern das es Programmtechnisch ist.
habe jetzt sämtliche Variablen von int auf unsigned char geändert, was die Programmlänge reduziert.

Ich bin zwar der Meinung das die CPU etwes schneller ist, aber wenn auch nicht wirklich viel.

Gut

Dann was mache ich noch im Programm:
Der Eingabebus arbeitet aus einer anderen oder älteren Entwicklung als Paralleler 16 Bit Bus.
Hier frage ich 16 Eingänge ab und speichere diese in Variablen ab.
Beispiel E1-16 -> vin1....vin16 die ich später abfragen kann.

Hier zähle ich per Takt über einen interen Timer einen Zähler (counter ++) immer hoch.
Pro Eingang mache ich nun folgendes

if (counter == 1 && in1 == 1)
{
vin1 = 1
}

if (counter == 1 && in1 == 0)
{
vin1 = 0
}

das mache ich natürlich 16x pro counterstellung..hier muss ich aber sagen wenn nur der eingangsbus programmiert ist,
die cpu sehr schnell ist.
erst wenn der i2c bus ins spiel kommt, also von der software wird er langsamer

sind vllt die if anweisungen das problem ?

vllt kann man diese routinen auch anders machen, arrays vllt ???

grüsse
Patrick

- - - Aktualisiert - - -


Was schieben ist bzw wie man schiebt, steht dort. Als Beispiel:
Ergebnis = (1<<2) | (1<<3);
(1<<2) ist ein Schiebebefehl => es wird eine 1 geladen und um 2 stellen nach links geschoben => es steht dann beim 3ten Bit im Ergebnis eine 1

Das Zeichen | bedeutet bitweises Oder

Beim oberen Beispiel hast du dann im Bit 2 und Bit 3 eine 1 stehen.

Ich würde mir die Grundlagen der Digitaltechnik anschauen.

MfG Hannes

Mahlzeit

ich muss sagen ich bin beruflich SPS Programmierer, kenne als Schiebeoperationen.
das Problem ist ich habe mit Codevision angefangen zu programmieren über einen kollegen und mir vieles selber angeignet.
Daher denke ich auch, ist das Programmieren wie ich es mache nciht immer optimal und vermutlich auch zu kompliziert.


Aber ich weiss was du meinst, könnte man versuchen

Klebwax
29.05.2019, 16:25
Tag
Das es an der Kommunikation des Busses liegt hatte ich auch nicht gedacht sondern das es Programmtechnisch ist.
habe jetzt sämtliche Variablen von int auf unsigned char geändert, was die Programmlänge reduziert.

Dein Prozessor wird im Datenblatt mit knapp 16 Mips beschrieben. Das wären 16 Millionen Additionen pro Sekunde. Deine 8 gehen da als Messfehler durch.



Dann was mache ich noch im Programm:
Der Eingabebus arbeitet aus einer anderen oder älteren Entwicklung als Paralleler 16 Bit Bus.
Hier frage ich 16 Eingänge ab und speichere diese in Variablen ab.
Beispiel E1-16 -> vin1....vin16 die ich später abfragen kann.

Hier zähle ich per Takt über einen interen Timer einen Zähler (counter ++) immer hoch.
Pro Eingang mache ich nun folgendes

if (counter == 1 && in1 == 1)
{
vin1 = 1
}

if (counter == 1 && in1 == 0)
{
vin1 = 0
}

das mache ich natürlich 16x pro counterstellung..hier muss ich aber sagen wenn nur der eingangsbus programmiert ist,
die cpu sehr schnell ist.
erst wenn der i2c bus ins spiel kommt, also von der software wird er langsamer

sind vllt die if anweisungen das problem ?

vllt kann man diese routinen auch anders machen, arrays vllt ???
Mit deiner Beschreibung kann ich nicht wirklich etwas anfangen.

Ich frag daher mal anders: wie oft machst du das mit dem MCP?

MfG Klebwax

modtronic
29.05.2019, 17:38
Dein Prozessor wird im Datenblatt mit knapp 16 Mips beschrieben. Das wären 16 Millionen Additionen pro Sekunde. Deine 8 gehen da als Messfehler durch.


Mit deiner Beschreibung kann ich nicht wirklich etwas anfangen.

Ich frag daher mal anders: wie oft machst du das mit dem MCP?

MfG Klebwax

Hallo

Zum eine, ich habe an der Problembehafteten CPU 5 MCP23017 im Einsatz, daher wird die Routine 10 mal benötigt.
Aber:
Ich habe das Problem gefunden. Das Problem kommt von der Takterzeugung welcher intern im Timer des MC als Overflow Interrupt Routine gemacht wird.

Ich habe mal die Durchlaufzeit des Programmteils gemessen und war irgendwo bei 1ms..
Daher kam mir der Gedanke das der Timer welcher ja auch Zeit braucht zum arbeiten vermutlich immer wieder unterbrochen wird wenn das Programm durchlaufen wird.
Vermutlich ist es daher auch so gewesen..Man sieht das auch dort an der RUN Led welche vom Timer zum blinken gebracht wird, da diese doch etwas unregelmässig blinkt wenn man sie beobachtet.
Habe hier dann mal ein Oskar angeschlossen und man sieht genau, im Verhältnis mit der Abfrage der Eingänge wie der Timer arbeitet.

Habe das jetzt anders Programmiert..und zack...geht !

Hier sieht man allerdings auch, wenn man sich vieles selber beibringt, das es viele Wege nach Rom gibt.

Frage ist, wäre es interessant mein Projekt mal Vorzustellen da es hier ja eigentlich um Robotik geht ?

Grüsse
Patrick