Go Down

Topic: Verständnis frage --> pinMode (Read 10827 times) previous topic - next topic

Doc_Arduino

Hallo,

aber alle Schieber einzeln mit "originalen Code"  funktionieren? Dann wird es nur am Code liegen. Dazu brauch ich etwas Ruhe ...

Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Muecke

Ja alle, Schieber funktionieren mit dem von uns ausgearbeiteten Original Code.



so hatte ich mir das zu beginn mal gedacht:
Code: [Select]
#include "Schieber_auslesen.h"     // Datei mit allen Fungzionen für die Messschiber laden
                                   // *.h bzw. *.c jenachdem was da jetzt das richtige ist, ...

int i = 0;      // vortlaufende ID Nr. wird hochgetält bei asugabe einer Neuen Messwert Zeile

void setup()
  {
    Serial.begin(9600);                      // Serielen monitor Definiren  
       // ********* Tabellen Kopf ausgeben
       Serial.print("ID");
       Serial.print("\t");
       Serial.print("Schieber 1");
       Serial.print("\t");
       Serial.print("Schieber 2");
       Serial.print("\t");
       Serial.print("Schieber 3");
       Serial.print("\t");
       Serial.print("Schieber 4");
       Serial.print("\t");
       Serial.print("Schieber 5");
       Serial.print("\t");
       Serial.print("Dehnungsmessstreifen");
       Serial.print("\n");
  }

void loop ()
  {

    if (digitalRead(Taster)== HIGH)           // warten bis Taster betätigt wurde
     {
        i+ = 1;                               // vortlaufende ID Nr. hochzählen
       Serial.print(i);                       // vortlaufende ID Nr. Ausgaben  
       Serial.print("\t");                    // Tabulattor ausgeben  
       Serial.print(Schieber1());             // Schieber Nr. 1 Auslesen udn Wert zurück geben
       Serial.print("\t");                    // Tabulattor ausgeben  
       Serial.print(Schieber2());             // Schieber Nr. 2 Auslesen udn Wert zurück geben
       Serial.print("\t");                    // Tabulattor ausgeben  
       Serial.print(Schieber3());             // Schieber Nr. 3 Auslesen udn Wert zurück geben
       Serial.print("\t");                    // Tabulattor ausgeben  
       Serial.print(Schieber4());             // Schieber Nr. 4 Auslesen udn Wert zurück geben
       Serial.print("\t");                    // Tabulattor ausgeben  
       Serial.print(Schieber5());             // Schieber Nr. 5 Auslesen udn Wert zurück geben
       Serial.print("\t");                    // Tabulattor ausgeben  
       Serial.print(Dehnungsmessstreifen());  // Dehnungsmessstreifen auslesen und Wert zurückgeben
       Serial.print("\n");                    // Zeilenumbruch erstellen
     }  // ENDE --> digitalRead(Taster)

  }  // ENDE --> void loop


jedoch bekomme ich oft nur eine 0.00 zurück

Quote
Wenn if ((millis() - temp_millis) > 100)  nicht zutrifft wird nichts zurück gegeben.
- Anfänger in allen Hinsicht - Bilder sichtbar einstellen
1  Bild Hochladen (Attachements); 2 Beitrag Save; 3 Anhang rechter Mausklick; "Adresse des Links kopieren"; 4 Beitrag „Modify"; 5 img-Tags mit dem kopierten Link einfügen; 6 Beitrag Save
DANKE

Doc_Arduino

Hallo,

den bisherigen Code in eine Lib auslagern funktioniert nicht so einfach. Das habe ich auch noch nie gemacht. Sehe dafür aber auch keine Notwendigkeit. Dein Taster ist auch nicht entprellt.
Was Du vor hast mit Dehnungsmeßstreifen usw.  ist nicht zufällig ein Studium's Projekt? Oder doch für privates basteln?

Ansonsten muß ich mich da erst wieder reindenken ...
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Muecke

mein Test Code habe ich nur mal grob runter geschrieben damit man versteht was ich machen möchte.


Wie gesagt für mich wäre es auch vollkommen OK wenn ich für Jeden Schieber eine separate Funktion habe,
wegen mir muss da keine PIN nr. etc übergeben werden.

Oh ne, ein Studium Projekt ist das nicht, ich Studiere nicht, ich bin im Vertrieb tätig, Beruflich habe ich mit dem Arduino oder mit Elektrik keine Berührungspunkte, das ist alles Privat was ich da mache.

wie gesagt der Code oben sollte nur veranschaulichen wie ich das umschreiben wollte.
dabei wurde mir dann her hinwies gegeben das es an der
Quote
Wenn if ((millis() - temp_millis) > 100)  nicht zutrifft wird nichts zurück gegeben.
Liegt, denn wenn das nicht zutrifft dann bekomme ich 0.00 zurück :-(

habe mir schon überlegt ob ich für Jedes Ergebnis eine Konstante erstelle, die Konstante hat dann das Ergebnis und die Fungzion gibt mir dann 0 bzw 1 zurück, so könnte ich die Fungzion auf True oder false prüfen und so lange die Fungzion aufrufen bis ich ein True bekomme und dann das Ergebnis ausgeben. 

Wäre das ein Ansatz? der in dir Richtige Richtung gehen würde?


oder ich kann dann in der Fungzion Prüfen ob ein Ergebnis erstellt wurde oder auch nicht,
wenn nicht dann wird die die Fungzion nochmal durchgearbeitet.
- Anfänger in allen Hinsicht - Bilder sichtbar einstellen
1  Bild Hochladen (Attachements); 2 Beitrag Save; 3 Anhang rechter Mausklick; "Adresse des Links kopieren"; 4 Beitrag „Modify"; 5 img-Tags mit dem kopierten Link einfügen; 6 Beitrag Save
DANKE

Serenifly

Quote
habe mir schon überlegt ob ich für Jedes Ergebnis eine Konstante erstelle,
Eine Konstante kann man nicht ändern. Du meinst eine globale Variable. Das ist aber ein ganz schlechter Programmierstil. Wenn dann übergibt man bei sowas für das Ergebnis einen Zeiger oder Referenz als Parameter. Genauso wie bei bestimmten String Funktionen ein Puffer für das Ergebnis übergeben musst.


Das ist bei Float aber nicht nötig. Du kannst hier einfach NAN (not a number) zurückgeben. Das ist ein spezieller Wert, der von keiner richtigen Zahl belegt wird:
http://www.nongnu.org/avr-libc/user-manual/group__avr__math.html#ga8abfcc76130f3f991d124dd22d7e69bc

in math.h gibt es dann auch isnan() fertig:
http://www.nongnu.org/avr-libc/user-manual/group__avr__math.html#ga468be9ed380771eca5a18e812b2470d4
Das liefert 1/true wenn die Variable NaN ist


Den Test per Hand zu machen ist etwas seltsam. Man vergleicht die Zahl mit sich selbst:
if(num != num)

Das ist true nur für NaN

Muecke

#35
Nov 21, 2014, 06:40 pm Last Edit: Nov 21, 2014, 06:44 pm by Muecke
ich verstehe was du meinst, ich bekomme es nur nicht zusammen :-(

mit den Links kann ich irgend wie nichts anfangen  :smiley-cry:  :smiley-cry:

daher habe ich mir einen Kleinen Test Code geschrieben:
Code: [Select]
// ******************************************************
//    NaN Prüfen in einer Funktion
// ******************************************************

#include "math.h"

int Taster = 3;                  // Taster PIN = Nr

void setup()
  {
    Serial.begin(9600);          // Seriele Einstellungen
    pinMode(Taster,  INPUT);     // Taster PIN = Eingang
  }

void loop()
  {
      while ( digitalRead(Taster)== LOW )  { }       // Waren bis Taster gedrückt wurde
      delay(100);                                    // kurze Pause machen damit sich nichts überschlägt
      while ( digitalRead(Taster)== HIGH)  { }       // Waren bis Taster gedrückt wurde

     if(isnan(NaN_Oder_Zahl()))
      {  Serial.println("Rückgabe ist NaN!");  }
      else
      {  Serial.println(NaN_Oder_Zahl());      }
  }
 
// ******************************************************
//         NaN Funktion
// ******************************************************   
 float NaN_Oder_Zahl()
  {
     return NaN;
  }


ich habe jetzt die "math.h" mit eingebunden, und kann somit auf NaN prüfen, die Frage ist nur wie kann ich das Definieren?

denn dabei bekomme ich eine Fehlermeldung:
Code: [Select]
     return NaN;
- Anfänger in allen Hinsicht - Bilder sichtbar einstellen
1  Bild Hochladen (Attachements); 2 Beitrag Save; 3 Anhang rechter Mausklick; "Adresse des Links kopieren"; 4 Beitrag „Modify"; 5 img-Tags mit dem kopierten Link einfügen; 6 Beitrag Save
DANKE

Serenifly

#36
Nov 21, 2014, 06:47 pm Last Edit: Nov 21, 2014, 06:48 pm by Serenifly
Das Makro ist NAN nicht NaN. Normalerweise schreibt man NaN in normalem Text, aber solche Makro Konstanten schreibt man nun mal meistens durchgehend in Großbuchstaben. Also NAN.

So steht es hier doch in math.h
#define NAN   __builtin_nan("")

Muecke

Danke.

Jetzt klappt es:  8)

Danke.

Dann mache ich mich mal dran das in den Code der Schieblehre einzubauen.



ach so das ist der Test Code, der funktioniert:

Code: [Select]
// ******************************************************
//    NaN Prüfen in einer Funktion
// ******************************************************

#include "math.h"

int Taster = 3;                  // Taster PIN = Nr

void setup()
  {
    Serial.begin(9600);          // Seriele Einstellungen
    pinMode(Taster,  INPUT);     // Taster PIN = Eingang
  }

void loop()
  {
      while ( digitalRead(Taster)== LOW )  { }       // Waren bis Taster gedrückt wurde
      delay(100);                                    // kurze Pause machen damit sich nichts überschlägt
      while ( digitalRead(Taster)== HIGH)  { }       // Waren bis Taster gedrückt wurde

     if(isnan(NaN_Oder_Zahl()))
      {  Serial.println("Rückgabe ist NaN!");  }
      else
      {  Serial.println(NaN_Oder_Zahl());      }
  }
 
// ******************************************************
//         NaN Funktion
// ******************************************************   
 float NaN_Oder_Zahl()
  {
     return NAN;
//     return 100;
  }     
- Anfänger in allen Hinsicht - Bilder sichtbar einstellen
1  Bild Hochladen (Attachements); 2 Beitrag Save; 3 Anhang rechter Mausklick; "Adresse des Links kopieren"; 4 Beitrag „Modify"; 5 img-Tags mit dem kopierten Link einfügen; 6 Beitrag Save
DANKE

Muecke

Juhu, ich habe es hin bekommen, auch wenn ich der Meinung bin das ich bei der Abfrage von NAN noch was Falsch mache, doch es Klappt :-)

genial.

DANKE an euch alle.



das ist der Code mit einen Schieber.
muss jetzt erst mal noch weg, werde dann später die Anderen Schieber auch noch einbauen, und den Code hier veröffentlichen.

DANKE noch mal an euch alle.


Code: [Select]
#include "math.h"
unsigned long temp_millis;
int Taster = 3;                  // Taster PIN = Nr
int i = 0;

float Ergebnis_Schieber5 = NAN;

void setup()
  {
    Serial.begin(9600);          // Seriele Einstellungen
    pinMode(Taster,  INPUT);     // Taster PIN = Eingang

    // ********* Tabellen Kopf
       Serial.print("ID");
       Serial.print("\t");
       Serial.print("Schieber 1");
       Serial.print("\t");
       Serial.print("Schieber 2");
       Serial.print("\t");
       Serial.print("Schieber 3");
       Serial.print("\t");
       Serial.print("Schieber 4");
       Serial.print("\t");
       Serial.print("Schieber 5");
       Serial.print("\t");
       Serial.print("Dehnungsmessstreifen");
       Serial.print("\n");
    // ********* Tabellen Kopf
  }
 
void loop()
  {
      while ( digitalRead(Taster)== LOW )  { }       // Waren bis Taster gedrückt wurde
      delay(100);                                    // kurze Pause machen damit sich nichts überschlägt
      while ( digitalRead(Taster)== HIGH)  { }       // Waren bis Taster gedrückt wurde

        i = i + 1;                            // vortlaufende ID Nr. hochzählen
       Serial.print(i);                       // vortlaufende ID Nr. Ausgaben 
       Serial.print("\t");                    // Tabulattor ausgeben 
       Serial.print(Schieber1());             // Schieber Nr. 1 Auslesen udn Wert zurück geben
       Serial.print("\t");                    // Tabulattor ausgeben 
       Serial.print(Schieber2());             // Schieber Nr. 2 Auslesen udn Wert zurück geben
       Serial.print("\t");                    // Tabulattor ausgeben 
       Serial.print(Schieber3());             // Schieber Nr. 3 Auslesen udn Wert zurück geben
       Serial.print("\t");                    // Tabulattor ausgeben 
       Serial.print(Schieber4());             // Schieber Nr. 4 Auslesen udn Wert zurück geben
       Serial.print("\t");                    // Tabulattor ausgeben 
       
          while ( isnan(Ergebnis_Schieber5) )  { Ergebnis_Schieber5 = Schieber5(); }   // Schieber Nr. 5 Auslesen udn Wert zurück geben
          Serial.print(Ergebnis_Schieber5);
          Ergebnis_Schieber5 = NAN;

       Serial.print("\t");                    // Tabulattor ausgeben 
       Serial.print(Dehnungsmessstreifen());  // Dehnungsmessstreifen auslesen und Wert zurückgeben
       Serial.print("\n");                    // Zeilenumbruch erstellen

  }  // ENDE --> void loop



float Schieber1()
  {
   
  }  // ENDE --> Schieber1
 
float Schieber2()
  {
  }  // ENDE --> Schieber2   
 
float Schieber3()
  {
  }  // ENDE --> Schieber3

float Schieber4()
  {
  }  // ENDE --> Schieber4

float Schieber5()
  {
    int Schieber_5_ClockPin = 24;  // Pin 24 das 2. Bit vom Port A (PINA PA2)
    int Schieber_5_DataPin  = 25;  // Pin 25 das 3. Bit vom Port A (PINA PA3)

    pinMode(Schieber_5_ClockPin, INPUT);
    pinMode(Schieber_5_DataPin,  INPUT);

    while (digitalRead(Schieber_5_ClockPin) == LOW) {}    // wenn CLOCK auf LOW, dann warten bis wieder HIGH
    temp_millis = millis();                               // aktuelle Zeitnahme
    while (digitalRead(Schieber_5_ClockPin) == HIGH) {}   // wenn CLOCK auf HIGH, warten bis wieder LOW
    if ((millis() - temp_millis) > 100)                   // wenn High-Pegel länger wie 100ms war, springe in 'decode' Funktion
      {

        long value = 0;
        byte SIGN_Bit = 0;                          // Vorzeichen Bit 21
     
          for (int i=0;i<24;i++)                    // 24 Durchläufe, 0 bis 23
            {           
              if ( PINA & ( 1 << PA3 ))             // wenn Data (Port.A Bit.3) HIGH ist,
                {                                   // eine 1 in die Variable 'value' an Bitnummer i
                  value |= 1UL << i;                // Syntax Hinweis aus dem Forum, wegen default 16 bit int Arithmetik
                }
                while ( !(PINA & (1 << PA2)))  { }  // solange warten bis Clock (Port.A Bit.2) wieder HIGH ist
                while (   PINA & (1 << PA2 ))  { }  // solange warten bis Clock (Port.A Bit.2) wieder LOW ist
            }  // for Schleifenende
   
           SIGN_Bit = (value >> 21) & B01;          // Vorzeichen Bit 21 separieren
           value = value & 0xFFFF;                  // nur Bit 0 bis Bit 15 behalten, den Rest davor nullen
           value = value >> 1;                      // und alles um ein Bit nach rechts schieben, Startsignal wird entfernt
           if (SIGN_Bit == 1)                       // wenn Vorzeichen-Bit gesetzt war, alles mit -1 multiplizieren
            { value = value * -1; }
//         Serial.println((float)value / 100);      // Kommastelle setzen und man erhält den endgültigen Meßwert  (Rückgabe wert)
         return (float)value / 100;                 // Kommastelle setzen und man erhält den endgültigen Meßwert  (Rückgabe wert)
        }
        return NAN;                                 // Fehlerwert ausgeben
  }  // ENDE --> Schieber5
 
float Dehnungsmessstreifen()
  {
  }  // ENDE --> Dehnungsmessstreifen 
- Anfänger in allen Hinsicht - Bilder sichtbar einstellen
1  Bild Hochladen (Attachements); 2 Beitrag Save; 3 Anhang rechter Mausklick; "Adresse des Links kopieren"; 4 Beitrag „Modify"; 5 img-Tags mit dem kopierten Link einfügen; 6 Beitrag Save
DANKE

Serenifly

#39
Nov 21, 2014, 08:09 pm Last Edit: Nov 21, 2014, 11:09 pm by Serenifly
Wieso übergibst nicht einfach den den Port und die Pin Nummer als Parameter?

So wie du das machen willst, verlierst du nämlich den eigentlich Sinn von Funktionen. Die Wiederverwertbarkeit von Code

Allgemeiner Test Code für die LED an Pin 13 (PB5):
Code: [Select]

void setup()
{
  pinMode(13, OUTPUT);
}

void loop()
{
  blink(&PORTB, PB5);
  delay(500);
}

void blink(volatile byte* port, byte pin)
{
  *port ^= _BV(pin);   //Pin mit XOR invertieren
}



Könnte bei dir dann so aussehen:
Code: [Select]

float schieber(volatile byte* port, byte pin1, byte pin2)
{
}


Siehe auch hier:
http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_port_pass

Das erzeugt aber auch etwas Overhead durch die indirekte Adressierung über Zeiger. Sollte aber hier noch kein Problem sein.


Das hier würde ich mir sparen:
Code: [Select]

int Schieber_5_ClockPin = 24;  // Pin 24 das 2. Bit vom Port A (PINA PA2)
int Schieber_5_DataPin  = 25;  // Pin 25 das 3. Bit vom Port A (PINA PA3)

pinMode(Schieber_5_ClockPin, INPUT);
pinMode(Schieber_5_DataPin,  INPUT);

Mach das entweder in setup() oder verwende das DDR Register. Den entsprechenden Pin im DDR Register auf 1 = Ausgang, 0 = Eingang.
Wobei das in setup() vollkommen reicht, da es sich nie ändert. Wieso das also bei jedem Funktionsaufruf neu machen?


Muecke

oh mann, du machst mich noch fertig.

das muss ich mir in ruhe anschauen wenn ich wieder am pc bin, wäre schon cool wenn das mit einer Funktion gehen würde.

ps. ja ich weiss das wie ich es aktuell mache überhaupt nicht perfekt ist.
jedoch ist das mein aktueller wissen stand.
- Anfänger in allen Hinsicht - Bilder sichtbar einstellen
1  Bild Hochladen (Attachements); 2 Beitrag Save; 3 Anhang rechter Mausklick; "Adresse des Links kopieren"; 4 Beitrag „Modify"; 5 img-Tags mit dem kopierten Link einfügen; 6 Beitrag Save
DANKE

Serenifly

#41
Nov 21, 2014, 11:04 pm Last Edit: Nov 21, 2014, 11:06 pm by Serenifly
Das ist eigentlich ganz einfach. Die Pin Nummer kannst du als Byte übergeben. Nichts ungewöhnliches daran.

Den Port musst du als Zeiger übergeben und dieser muss volatile sein, weil das Register so in der avr libc definiert ist. Daher einfach volatile byte* port als Parameter. Wenn man direkt PORTB als byte übergeben würden, hätte man den Inhalt des Registers!

Bei Aufruf übergibt man dann mit & die Adresse: &PORTB
Genauso wie bei Zeigern allgemein.

Und wenn du den Port ansprichst musst du den Zeiger mit * dereferenzieren:
*port =
Damit du das hast worauf der Zeiger zeigt und nicht etwas auf die Zeiger-Variable selbst zuweist.

Und bei PINA geht das genauso.

Muecke

du darfst nicht so schnell mit mir das machen, ... ich bin nicht vom Fach :-(


Kannst das Beispiel:
Quote
Allgemeiner Test Code für die LED an Pin 13 (PB5):
mal genauer erklären, .. ich komme da nicht ganz mit.
könnten wir da einen Test Code machen mit dem wir die LED 13 Blinken lassen über die Register ?
- Anfänger in allen Hinsicht - Bilder sichtbar einstellen
1  Bild Hochladen (Attachements); 2 Beitrag Save; 3 Anhang rechter Mausklick; "Adresse des Links kopieren"; 4 Beitrag „Modify"; 5 img-Tags mit dem kopierten Link einfügen; 6 Beitrag Save
DANKE

Serenifly

#43
Nov 21, 2014, 11:57 pm Last Edit: Nov 21, 2014, 11:59 pm by Serenifly
Quote
könnten wir da einen Test Code machen mit dem wir die LED 13 Blinken lassen über die Register ?
Das ist genau was der Code macht. Lediglich um den Ausgang zu setzen, habe ich pinMode() verwendet.

Was gibt es da groß zu erklären? Das sind doch nur drei Zeilen die was interessantes enthalten und die habe ich schon erklärt :s

Code: [Select]

void blink(volatile byte* port, byte pin)
{
  *port ^= _BV(pin);   //Pin mit XOR invertieren
}

Eine Funktion die einen Zeiger auf ein Port Register und eine Pin Nummer als Parameter hat.

^= ist ein Exlusiv-Oder:
http://de.wikipedia.org/wiki/Kontravalenz
Das invertiert wie der Kommentar sagt den Pin

_BV() steht für "bit value" und ist lediglich ein Makro für "1 << n"
Mann kann genauso *port ^= 1 << pin schreiben

Wichtig ist hier das * vor "port", da du den Inhalt der Adresse ansprechen willst und nicht die Adresse selbst.

Und beim Aufruf übergibt man wie gesagt mit & die Adresse (ein Zeiger ist nichts anderes als eine Adresse):
Code: [Select]

blink(&PORTB, PB5);



Du würdest es so ähnlich machen:
Code: [Select]

float schieber(volatile byte* port, byte clock, byte data)
{
    if ( *port & ( 1 << data ))
      ....
 
    while ( !(*port & (1 << clock)))  { }

   ....
}


Und so aufrufen:
Code: [Select]

float value = schieber(&PINA, PA2, PA3);


Sollte rein theoretisch funktionieren.

Muecke

Wir bleiben bei dem Blinkenden Beispiel.


hier Blinkt meine LED an PIN 13
Code: [Select]
void setup()
  {
    pinMode(13, OUTPUT);
  }

void loop()
  {
    digitalWrite(13, HIGH);   
    delay(1000);             
    digitalWrite(13, LOW);   
    delay(1000);           
  }



bei deinem Code Blinkt die LED nicht
Code: [Select]

void setup()
{
  pinMode(13, OUTPUT);
}

void loop()
{
  blink(&PORTB, PB5);
  delay(500);
}

void blink(volatile byte* port, byte pin)
{
  *port ^= _BV(pin);   //Pin mit XOR invertieren
}



du weist doch ich bin nicht der schnellste bei der Sache.
- Anfänger in allen Hinsicht - Bilder sichtbar einstellen
1  Bild Hochladen (Attachements); 2 Beitrag Save; 3 Anhang rechter Mausklick; "Adresse des Links kopieren"; 4 Beitrag „Modify"; 5 img-Tags mit dem kopierten Link einfügen; 6 Beitrag Save
DANKE

Go Up