Wie verwende ich einen zweiten Map Befehl über eine zweite Wertetabelle?

Hallo,
ich habe einen einfachen Triggergenerator geschrieben, der über ein Poti einen Takt erzeugt.
Mit dem ersten MAP Befehl skaliere ich den Poti Wert 0-1024 auf die gewünschte Taktfrequenz 30000 - 100ms in die Variable trigValue. Mit dem zweiten MAP Befehl möchte ich die Variable trigValue in die Variable dispValue skalieren, um diese dann zur Anzeige zu bringen.
Das funktioniert auch alles soweit, aber leider nicht die zweite Skalierung des Display Wertes über das zweite Mapping. Für den MAP Befehl nutze ich übigens in beiden Fällen eine Wertetabelle.

Bin leider ratlos - hängt jetzt nur noch an dieser "Kleinigkeit"!
Freu mich sehr über jeden hilfreichen Tipp!
Dirk

Anbei der Code:

/*
Triggersimulator, basierend auf dem Arduino Nano
Speed Auswahl über ein 10kOhm Poti
Anzeige Status über ein SSD1306 128x64 OLED Display
Adresse vom Display ist die 0x3C
Ausgabe auf einen Digitalen Ausgang und von da auf einen Transistor, um 24V zu schalten
*/


// constants won't change. Used here to set a pin number:
const int ledPin1 = LED_BUILTIN;  // the number of the LED pin
const int ledPin2 = 5;            // select the pin for the LED
const int sensorPin = A0;         // select the input pin for the potentiometer


// Variables will change:
int ledState = LOW; 
int trigValue = 0;
int dispValue = 0;

unsigned long previousMillis = 0;  // will store last time LED was updated

#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels

// On an arduino UNO:       A4(SDA), A5(SCL)
#define OLED_RESET -1        // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C  ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define LOGO_HEIGHT 16
#define LOGO_WIDTH 16

short mapping1[25] = {30000, 12000, 6000, 4000, 3000, 2400, 1200, 800, 600, 480, 400, 343, 300, 267, 240, 218, 200, 185, 171, 160, 150, 133, 120, 109, 100};
            //  m/min   2      5     10    15    20    25    50   75   100  125  150  175  200  225  250  275  300  325  350  375  400  450  500  550  600
short mapping2[25] = {2, 5, 10, 15, 20, 25, 50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300, 325, 350, 375, 400, 450, 500, 550, 600};

void setup() {
  // set the digital pin as output:
  pinMode(ledPin1, OUTPUT);
  // declare the ledPin as an OUTPUT:
  pinMode(ledPin2, OUTPUT);

  Serial.begin(9600);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;  // Don't proceed, loop forever
  }

  // Clear the buffer
  display.clearDisplay();

  display.setTextSize(4);               
  display.setTextColor(SSD1306_WHITE);  
  display.setCursor(30, 16);            
  display.println(F("DSC"));

  display.display();
  delay(2000);

  // Invert and restore display, pausing in-between
  display.invertDisplay(true);
  delay(500);
  display.invertDisplay(false);
  delay(500);
  display.invertDisplay(true);
  delay(500);
  display.invertDisplay(false);
  delay(500);
  display.invertDisplay(true);
  delay(500);
  display.invertDisplay(false);
  delay(500);
}

void loop() {

  display.clearDisplay();

  display.setTextSize(1, 2);            
  display.setTextColor(SSD1306_WHITE);  
  display.setCursor(13, 0);             
  display.println(F("Trigger Simulator"));
  display.setTextSize(1);    
  display.setCursor(4, 20);  
  display.println(F("Skalierung Metertakt"));
  display.setTextSize(1);     
  display.setCursor(55, 57);  
  display.println(F("DSC V1_04_24"));
  display.setTextSize(2);     
  display.setCursor(65, 33);  
  display.println(F("m/min"));

  display.display();

  // read the value from the sensor:
  trigValue = mapping1[map(analogRead(sensorPin), 0, 1024, 0, 25)];  // Poti scaling
  dispValue = mapping2[map(trigValue, 100, 30000, 0, 25)];

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= trigValue) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;


    if (dispValue <= 0) {

      digitalWrite(ledPin1, LOW);
      digitalWrite(ledPin2, LOW);

      display.setTextSize(2);     
      display.setCursor(10, 35);  
      display.println(F("0"));
      display.display();

    } else {

      display.setTextSize(2);     
      display.setCursor(10, 35);  
      display.println(dispValue);
      display.display();

  display.setTextSize(1);             
  display.setCursor(10,55);             
  display.println(trigValue);
  display.display();



      digitalWrite(ledPin1, HIGH);
      digitalWrite(ledPin2, HIGH);
      delay(200);
      digitalWrite(ledPin1, LOW);
      digitalWrite(ledPin2, LOW);
    }
  }
}

Was soll das machen du invertiert den Inhalt 6X verlierst dabei 3sek.
Erst mach alle delay() weg :wink:

Jetzt habe verstanden bei dem angezeigtem Wert soll es "blinken" :wink:

1 Like

Hallo
Ich hab das nicht verstanden , wozu ist das Array mapping[] da ?

Schau dir in der Referenz noch mal die Verwendung von map() an.

Jetzt meine verstehe was @dicsoftxl will, nämlich die werte trigValue und dispValue anzeigen wen die sich ändern. ich wurde das mit switch , case machen machen mit wert Bereich, wird zwar unzählige case geben aber danach sollte funktionieren.

case 480 ... 600:
 map ();
wert anzeigen......
break;

Ja korrekt, ist nur ein kleiner "Gag" während dem Boot Vorgang.
Das OLED Display blinkt entsprechend der Pausen.

ersetze mal:

  // read the value from the sensor:
  trigValue = mapping1[map(analogRead(sensorPin), 0, 1024, 0, 25)];  // Poti scaling
  dispValue = mapping2[trigValue];
  unsigned long currentMillis = millis();

Wobei das gesamte Konstrukt sehr abenteuerlich ist.

OK im setup geht das :wink: habe übersehen dass das im setup ist.

Über das Mapping Array möchte ich sicherstellen, das genau diese Werte zugewiesen werden und keine willkürliche Berechnung zwischen min und max.
Ich benötige präzise die Stufen aus dem ersten Array, welche auch tadellos funktionieren.
Leider funktioniert das zweite Array nicht, obwohl es keinerlei Fehlermeldung gibt.
Im zweiten Array weise ich den entsprechenden "Frequenzen" dann eine Drehzahl in m/min zu.

Macht schöne Laufschrift. habe gerade ein display am Tisch ist zwar mit SH 1116 aber hat was angezeigt :wink:

dispValue = mapping2[trigValue];
führt zu einem sehr hohen Anzeigewert über 16000, welcher so auch nicht in meinem zweiten Array zu finden ist. Zudem wird der Anzeigewert nicht dynamisch nachgeführt, wenn ich das Poti verstelle.

AH!
Ich habs ... Moment....

Das wäre dann der Ansatz:

  // read the value from the sensor:
  byte myMapping = map(analogRead(sensorPin), 0, 1024, 0, 25);
  trigValue = mapping1[myMapping];  // Poti scaling
  dispValue = mapping2[myMapping];
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= trigValue)

Du hast übrigens eine Warnung:

warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   if (currentMillis - previousMillis >= trigValue)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
2 Likes

Du bist ja der Hammer!!! :hugs:
Das funktioniert genau wie von mir gewünscht!
Vielen Dank - hast mir den Tag gerettet... und den meiner Frau! :wink:

Magst Du mir eventuell noch kurz erläutern, was genau da jetzt passiert?
Bin noch ziemlicher Anfänger und möchte sehr gerne verstehen, was in meinem Code stattfindet.

Ja gerne.
Du verwendest das mapping, um auf das entsprechende Element zuzugreifen.
Dein Code für den ersten Wert hättest Du auch für den zweiten nehmen können.

  // read the value from the sensor:
  trigValue = mapping1[map(analogRead(sensorPin), 0, 1024, 0, 25)];  // Poti scaling
  dispValue = mapping2[map(analogRead(sensorPin), 0, 1024, 0, 25)];
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= trigValue)

Das ist aber gefährlich, da Du für jedes Mappen den Analogwert neu einliest.
Ändert der sich dazwischen, passt das nicht.
Um das zu verhindern nehme ich eine HilfsVariable myMapping und fülle diese mit dem Map-Wert.
Dieser wird dann weiterverwendet um das entsprechende Element auszuwählen.

Es ginge auch eine andere Variante:

  // read the value from the sensor:
  uint16_t myValue = analogRead(sensorPin);
  trigValue = mapping1[map(myValue, 0, 1024, 0, 25)];  // Poti scaling
  dispValue = mapping2[map(myValue, 0, 1024, 0, 25)];

Damit würdest Du den Value aus den analogread weiterverwenden.
Das macht dann Sinn, wenn Du z.B. in mapping1 und mapping2 eine unterschiedliche Anzahl Elemente hättest.
Sonst nicht, denn die Berechnung verbraucht unnötig Rechenzeit.

Alles klar?

2 Likes

Man könnte natürlich auch ein struct verwenden. Darin ist zusammengefasst, was zusammen gehört.

struct Data {
  const uint16_t trig;
  const uint16_t disp;
};

const Data dataMap[25] {
  {30000, 2}, {12000, 5}, {6000, 10}, {4000, 15}, {3000, 20},
  {2400, 25}, {1200, 50}, { 800, 75}, {600, 100}, {480, 125},
  {400, 150}, {343, 175}, {300, 200}, {267, 225}, {240, 250},
  {218, 275}, {200, 300}, {185, 325}, {171, 350}, {160, 375},
  {150, 400}, {133, 450}, {120, 500}, {109, 550}, {100, 600}
};

Dann

 byte index = map(analogRead(sensorPin), 0, 1024, 0, sizeof(dataMap) / sizeof(dataMap[0]));
  Data show = dataMap[index];
  Serial.println(show.trig);
  Serial.println(show.disp);

Aber das nur nebenbei...

1 Like

Ich hatte ja gehofft, noch eine Antwort zu bekommen...
Der Sketch mit der Festlegung der Anzahl der Elemente war schon fertig... :wink:

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.