Hallo und guten Morgen,
bevor ich anfange, dumme Fragen zu stellen, stelle ich mich kurz vor:
Mein Name ist Bernd, komme aus der Steiermark (AT), bin 28 jahre jung,
gelernter Mess- & Regeltechniker.
Ich arbeite als Elektro-Instandhalter in einem Industriebetrieb, den ich
hier aber nicht vorstellen möchte.
Und da wäre ich auch schon bei meinem Problem:
Ich habe eine Walze mit einem Umfang von 239cm. Bei jedem Umlauf wird
ein Initiator (ind. Näherungssensor) betätigt, welcher mir einen
24V-Impuls für die Dauer der Belegung ausgibt.
Über ein Auswertegerät werden diese Impulse erfasst und über IC's der
40er-Baureihe umgewandelt.
Für jeden Meter, also 100cm, wird ein Impuls aus diesem Auswertegerät
ausgegeben (und an einen externen Laufmeterzähler[Impulszähler]
geschickt), dementsprechend wird auch der Zählerwert um 100
dekrementiert. Dies ist so lange der Fall, so lange der Zählwert >= 100
ist.
Sollten nun 100 Impulse von der Walze kommen, so entspricht dies einer
Länge von 100*239cm = 23900cm = 239m. Es sollten nun auch auf dem
externen Zähler der Zahlenwert "239" zu lesen sein.
Leider funktioniert der Code, den ich bis jetzt geschrieben habe, nicht.
bzw. wird nur ein Impuls ausgegeben. Wahrscheinlich ist es eh nur eine
Kleinigkeit, die ich übersehe, oder ein Denkfehler. Aber ich komme nicht
mehr weiter.
Anbei der Code: Vl. kann mir hier jemand weiterhelfen.
Schon mal danke im Vorraus ;-)
1
#include<avr/io.h>
2
#include<util/delay.h>
3
4
5
intmain(void)
6
{
7
8
DDRA=0x00;// PORTA = Eingänge
9
DDRB=0xff;// PORTB = Ausgänge
10
// DDRD = 0xff; // PORTD = Ausgänge
11
12
PORTA=0xff;
13
PORTB=0b00000000;// Ausgänge ausschalten
14
// PORTD = 0x00; // Ausgänge ausschalten
15
16
inti=0;// Zaehler deklarieren und auf Default (0) setzen
PS: Die Anlage verfügt über eine SPS, die das Laufmetersignal von einem
Laserzähler erhält und auch dementsprechend umrechnet und abarbeitet.
Ich habe auch schon ein SPS-Programm für den Anwendungsfall mit dem
Initiator geschrieben, jedoch ist dieser Ini nur dann im Einsatz, wenn
der Laserzähler ausfällt.
Hi, ich würde schonmal nicht mit delay arbeiten, was ist wenn während
des delays ein weiterer Impuls kommt, den erkennst du dann garnicht.
So 100% hab ich die Aufgabenstellung zwar noch nicht geblickt aber 2
Sachen fallen mit auf:
1. Integer ist bei guten 32000schluss, dann gibts einen Überlauf
2. Du verwendest keine Flankenauswertung, d.h. wenn der Imopuls länger
als 250ms da ist wird er 2 mal gezählt
Bernd M. schrieb:
Also wenn ich Deinen Code mal etwas verdichte, komme ich auf das:
i = i + 239; // Zaehler inkrementieren
while (i >= 100) // vergleiche Zählerwert mit Vorgabe
{
i = i - 100; // Solange i >= 100, 100 von i abziehen
} // Ende while-Schleife
???
danke für die flinke antwort ;-)
zu deinen Antworten:
1) die Eingangs-Impulse sollen nicht gesammelt und danach einzeln,
sondern kontinuierlich, d.h bei i >= 100, ausgegeben werden.
2) Der Impuls ist auch bei einer minimalen Maschinengeschwindigkeit
relativ kurz (ca. 200ms), die 250ms sind nur für Testzwecke eingestellt.
Das mit dem "Verzählen" ist bei einer Tagesproduktion von ~400.000lfm
nicht so genau ;-)
Wie schaut's code-technisch aus: warum will das bei mir nicht
funktionieren?
danke
ach und noch was fällt mir auf...wenn du den ausgangsimouls abschaltest
müsste ja auch noch 50ms als delay rein, sonst schalter er immer den
ausgang 50ms an, dann für 1 zyklus aus und sofort wieder an...darin
dürfte wohl dein haupter fehler liegen...
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRA = 0x00; // PORTA = Eingänge
DDRB = 0xff; // PORTB = Ausgänge
// DDRD = 0xff; // PORTD = Ausgänge
PORTA = 0xff;
PORTB = 0b00000000; // Ausgänge ausschalten
// PORTD = 0x00; // Ausgänge ausschalten
double i = 0;
int Input_neu = 0;
int Input_alt = 0;
while(1) // Beginn der Endlosschleife
{
Input_neu = (PINA & (1 << PINA0);
if (Input_neu == 1 && Input_alt ==0)
{
i = i + 239; // Zaehler inkrementieren
} // Ende if-Schleife
Input_alt = (PINA & (1 << PINA0);
while (i >= 100) // vergleiche Zählerwert mit Vorgabe
{
i = i - 100; // Solange i >= 100, 100 von i abziehen
PORTB = 0x03; // Ausgang für Zähler
_delay_ms(50); // Impulsdauer
PORTB = 0x00; // Asugang wieder löschen
_delay_ms(50); // Nulldurchgang des Impulses
} // Ende while-Schleife
} // Ende while(1)-Schleife
} // Ende main-Schleife
danke für die prompte bedienung, meine herrschaften, ich werde das ganze
gleich einmal versuchen.
bei korrekter funktion gibts natürlich ein feedback ;-)
danke und schönen tag noch
Bernd M. schrieb:> danke für die prompte bedienung, meine herrschaften, ich werde das ganze> gleich einmal versuchen.>> bei korrekter funktion gibts natürlich ein feedback ;-)
Wird allmählich knapp mit den Delays bei 400.000lfm pro Tag.
400.000 m / (2,39m * 86400 s) = 1,94 Umdrehungen pro Sekunde
durchschnittlich.
Pro Umdrehung hast Du aber schon 200 ms Delay am Anfang und bei jedem
Substraktionsvorgang zweimal 50 ms, also insgesamt 2* 2*50 = 200 ms.
Macht zusammen 400 ms Delay. Auf diese Art messbare Höchstdrehzahl: 2,5
pro Sekunde.
Wenn also die Höchstgeschwindigkeit der Maschine nur um 25% höher liegt
als die durchschnittliche Tagesgeschwindigkeit, funktioniert es mit
diesen Delays nicht mehr. Vermutlich.
Und wenn bei Stillstand der Maschine der Taster S1 auf dauernd ON steht,
wird laufend hochgezählt, trotz stehender Maschine?
Bernd M. schrieb:> Input_neu = (!(PINA & (1 << PINA0)));> if (Input_neu == 1 && Input_alt ==0)> {> i = i + 239; // Zaehler inkrementieren> }
Ja, so mache ich das bei meinen einfachen tastenbetätigten
Blinkschaltungen auch immer: Anzahl der gedrückten Tasten merken, und
wenn im nachfolgenden Schleifendurchlauf die Anzahl der gedrückten
Tasten größer ist als vorher, dann die entsprechende Aktion ausführen.
> while (i >= 100) // vergleiche Zählerwert mit Vorgabe> {> i = i - 100; // Solange i >= 100, 100 von i abziehen> PORTB = 0x03; // Ausgang für Zähler> _delay_ms(200); // Impulsdauer> PORTB = 0x00; // Asugang wieder löschen> _delay_ms(200); // Pausedauer> }
Da i über 300 werden kann, wird die Schleife bis zu dreimal durchlaufen,
mit je 2*200 ms delay = 3*2*200 = 1200 ms. Das funktioniert nur mit
Drehzahlen der Walze von unter eins pro Sekunde. Nach meiner groben
Rechnung und Deinen Angaben dreht die Walze aber fast zweimal pro
Sekunde, oder? Ich würde nochmal genau prüfen, ob nicht nur überhaupt
gezählt wird, sondern bei entsprechender Drehzahl der Maschine auch
alles gezählt wird und wegen der Delayzeiten nicht manche
Zählerweiterschaltungen ausfallen.
Kann Jürgen nur beipflichenten, falls das der Fall sein sollte muss man
die ImpulsAUSGABE in ein Timergesteuertes Interrupt verlagern was aber
auch kein großer Akt ist. Kannst dich ja diesbezüglich bei Bedarf
nochmal melden.
Ansonsten freuts mich dass es funzt :-)
Hallo Jürgen,
der Code stammt von soundmachine (an dieser Stelle nochmals danke
dafür).
Wie gesagt, die Delayzeiten sind nur deswegen so hoch, damit ich die
quasikorrekte Funktion auf meinem Eval-Board testen kann. In der
"echten" Steuerung werden die Werte natürlich auf ein Mindestmaß
reduziert, sodass sich hier "hoffentlich" die impulse nicht
überschneiden.
Bei 400m/min und 2,39m/Umdrehung, also knapp 170 Umdrehungen/min wird
das zwar etwas "empirisch", sollte aber auch realisierbar sein.
Bernd M. schrieb:> 2) Der Impuls ist auch bei einer minimalen Maschinengeschwindigkeit> relativ kurz (ca. 200ms)
Das sind für einen MC Ewigkeiten.
Ich würde zum Entprellen raten. Das unterdrückt dann auch Störimpulse
(lange Leitung).
Z.B. bei 4-fach Abtastung und 5ms Entprellzeit muß ein Puls mindestens
20ms lang sein.
Bernd M. schrieb:> Das mit dem "Verzählen" ist bei einer Tagesproduktion von ~400.000lfm> nicht so genau ;-)
Du solltest schon so programmieren, daß es ganz genau ist. Seitens des
MCs gibts da kein Limit.
Sobald Du Fehler im Programm hast, weißt Du ja nicht, wie ungenau Du
dadurch wirst.
Peter
deine uC hat vermutlich einen ext. interrupt. Den sollte man auch nutzen
wenn man ihn sowieso hat. du kannst sogar einstellen wann er auslösen
soll (steigende flanke, fallende, beide, usw.)
zum entprellen könnte man einen der internen Timer nutzen
frank schrieb:> deine uC hat vermutlich einen ext. interrupt. Den sollte man auch nutzen> wenn man ihn sowieso hat. du kannst sogar einstellen wann er auslösen> soll (steigende flanke, fallende, beide, usw.)
Würde ich ehrlich gesagt nicht machen.
Bei 40cm Walzenradius hat er ja nicht beliebig hohe Drehzahlen. D.h. mit
Polling in der üblichen PeDa Entprellkonfiguration sollte er eigentlich
das Auslangen finden. Selbst wenn der Sensor, der da drann hängt nicht
prellt, schadet es auch nicht, da eine Entprellung drann zu hängen. Wie
Peter schon sagte: letztendlich kommt das der Störsicherheit zu gute.
Und das soll ja noch nie geschadet haben.
Externer Interrupt ist ok, wenn man nicht Entprellen muss UND das ganze
auch nach schnell sein muss. Wenn beides aber nicht gegeben ist, ist
PeDa Entprellen auch nicht übermässig mehr Aufwand und hat den Vorteil,
dass er vom Entwicklungsbrett zur realen Anlage nichts verändern muss.
Und die while-Schleife
while( i > 100 )
hätte ich durch ein if ersetzt und das sukzessive Runterzählen der
Hauptschleife überlassen.
fehlt noch der timer zur entprellung sowie die ausgabe der daten. das
ganze ist mehr oder minder aus dem gedächnis, möchte nicht ausschließen
registersettings vergessen zuhaben :P