Тахометр на светодиодной ленте

Тема в разделе "Arduino & Shields", создана пользователем santer, 26 ноя 2017.

  1. santer

    santer Нерд

    Всем доброго дня.
    Есть задача построить тахометр на ленте WS2812B
    В зависимости от оборотов растет столбик + меняется цвет.
    Но столкнулся с проблемой. Как-то криво работает функция map();
    По определению данная функция берет значение переменной (в указанном диапазоне ) и преобразовывает в другом диапазоне. Если значения входной переменной выходят за пределы диапазона, то выставляется крайнее значение в указанном выходном диапазоне.

    В коде я четко указываю крайние значения 1-255, ро почему-то при выходе за пределы диапазона
    получаю не 1, а отрицательные значения, что приводит к засвету ленты не верным цветом.
    В мониторе порта показан переход границы в 4500 оборотов, когда Зеленая составляющая должна быть равной 1, а она вылазит в отрицательные значения.
    Кто может подсказать в чем кроется ошибка?


    вот что получаю с порта
    ========================
    RPM= 4426 RED= 124 GREEN= 6 BLUE= 0
    RPM= 4437 RED= 124 GREEN= 6 BLUE= 0
    RPM= 4433 RED= 125 GREEN= 5 BLUE= 0
    RPM= 4456 RED= 125 GREEN= 4 BLUE= 0
    RPM= 4455 RED= 126 GREEN= 4 BLUE= 0
    RPM= 4477 RED= 126 GREEN= 4 BLUE= 0
    RPM= 4493 RED= 127 GREEN= 3 BLUE= 0
    RPM= 4507 RED= 127 GREEN= 2 BLUE= 0
    RPM= 4524 RED= 128 GREEN= 1 BLUE= 0
    RPM= 4542 RED= 129 GREEN= 0 BLUE= 0
    RPM= 4536 RED= 129 GREEN= -1 BLUE= 0
    RPM= 4555 RED= 129 GREEN= -1 BLUE= 0
    RPM= 4561 RED= 130 GREEN= -2 BLUE= 0
    RPM= 4573 RED= 130 GREEN= -2 BLUE= 0
    RPM= 4589 RED= 131 GREEN= -3 BLUE= 0
    RPM= 4604 RED= 131 GREEN= -4 BLUE= 0
    RPM= 4619 RED= 132 GREEN= -4 BLUE= 0
    RPM= 4626 RED= 133 GREEN= -5 BLUE= 0
    RPM= 4623 RED= 133 GREEN= -6 BLUE= 0
    RPM= 4626 RED= 133 GREEN= -5 BLUE= 0
    RPM= 4641 RED= 133 GREEN= -6 BLUE= 0
    RPM= 4647 RED= 133 GREEN= -6 BLUE= 0


    ========================


    вот скетч
    =====================================
    /* LedStripGradient: Example Arduino sketch that shows
    * how to control an Addressable RGB LED Strip from Pololu.
    *
    * To use this, you will need to plug an Addressable RGB LED
    * strip from Pololu into pin 12. After uploading the sketch,
    * you should see a pattern on the LED strip that fades from
    * green to pink and also moves along the strip.
    */

    #include <PololuLedStrip.h>
    // Create an ledStrip object and specify the pin it will use.
    PololuLedStrip<12> ledStrip;
    // Create a buffer for holding the colors (3 bytes per color).
    #define LED_COUNT 12
    rgb_color colors[LED_COUNT];
    //конец лед ленты

    volatile unsigned long lastflash;
    int ledtaho, ledtahomax, ledtahodelta, RED, GREEN, BLUE, leddelta;
    volatile int RPM;

    void setup()
    {
    attachInterrupt(0, sens, RISING);
    Serial.begin(9600);
    pinMode(2, INPUT_PULLUP);

    for (uint16_t i = 0; i < LED_COUNT; i++)
    {
    colors = rgb_color(0, 0, 0);
    ledStrip.write(colors, LED_COUNT);
    }

    }

    void loop()
    {

    RPM = constrain(RPM, 0, 7500);
    // ledtaho = abs(RPM/550);
    ledtaho = abs(constrain((RPM/550), 0, 12));
    /* Serial.print("RPM ");
    Serial.println(RPM);
    Serial.print("ledtaho ");
    Serial.println(ledtaho);*/
    Serial.print("RPM= ");
    Serial.print(RPM);

    Serial.print(" RED= ");
    Serial.print(RED);
    Serial.print(" GREEN= ");
    Serial.print(GREEN);
    Serial.print(" BLUE= ");
    Serial.println(BLUE);

    if ((micros()-lastflash)>1000000) //если сигнала нет больше секунды
    {
    RPM=0; //считаем что RPM 0
    for (uint16_t x = 0; x > LED_COUNT; x--)
    {
    colors[x] = rgb_color(0, 0, 0);
    ledStrip.write(colors, LED_COUNT);

    delay (10);
    }

    }

    // ledtaho = abs(RPM/550);

    // RPM = constrain(RPM, 0, 7500);
    // ledtaho = constrain(ledtaho, 0, 12);

    if (ledtaho > ledtahomax)
    {
    ledtahomax = ledtaho;
    }

    RED = map(RPM, 1500, 7500, 1, 255);
    GREEN = map(RPM, 0, 4500, 255, 1);
    BLUE = 0;

    for (uint16_t i = 1; i < ledtaho; i++)
    {
    colors = rgb_color(RED, GREEN, BLUE);
    ledStrip.write(colors, ledtaho);

    delay (10);
    }

    for (uint16_t x = ledtahomax; x > ledtaho; x--)
    {
    colors[x] = rgb_color(0, 0, 0);
    ledStrip.write(colors, ledtahomax);

    delay (10);
    }

    }

    void sens()
    {
    RPM=abs(120/((float)(micros()-lastflash)/1000000)); //расчет
    lastflash=micros(); //запомнить время последнего оборота
    }
    ===============================================
     
  2. ORLENOK

    ORLENOK Гик

    Если функция map() действительно такая:
    Код (C++):
    long map(long x, long in_min, long in_max, long out_min, long out_max)
    {
      return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    }
    То тут никак не обрабатывается выход за границы и соответственно значения вне границы.
    Можно после map использовать constrain()
    Код (C++):
    GREEN = constrain(GREEN,255,1)
     
    Tomasina нравится это.
  3. santer

    santer Нерд

    ок попробую. Спасибо.
     
  4. Tomasina

    Tomasina Сушитель лампочек Модератор

    ORLENOK прав, функция map() занимается только преобразованием диапазонов. Обеспечить контроль границ диапазона - заботы программиста (в данном случае проще всего взять constrain()).