Глобальная переменная не обновляется…

Я разрабатываю небольшой проект по поддержанию температуры резервуара для меднения и рабочего цикла фильтрующего насоса. Я использую платформу Adafruit Feather для хранения 8-сегментной матрицы в сочетании с Teensy 3.2 (на щите из перьев) для расчета и отображения температуры. На A0 имеется емкость 10K и полоска неопикселя 8 сегментов для установки и отображения рабочего цикла насоса от 1 до 8, соответствующего .125*часу и 100% вкл. Существует также переключатель push и hold set для управления настройкой целевой точки температуры с помощью той же кастрюли.

Вещи, которые работают: Почти все! Вещь, которая не работает:

Изменение ручки рабочего цикла (которая изменяет глобальную переменную рабочего цикла) после включения устройства, по-видимому, не изменяет время включения/выключения, кроме как для успешной смены дисплея NeoPixel. Если устройство включено в определенный рабочий цикл, программа успешно выполнит этот рабочий цикл. Во время работы, если я изменю рабочий цикл на 8, я не получу "100% включено". Другими словами, изменение переменной рабочего цикла, по-видимому, не изменяет переменные времени включения и выключения в коде во время выполнения.

Вопрос: Что мне нужно сделать, чтобы настройка рабочего цикла работала на лету?

О... Это изменчивое объявление с плавающей точкой было моей последней отчаянной попыткой, пожалуйста, проигнорируйте / простите. ;-)

Надеюсь, исправление так же просто, как и код. ;-) Я просто этого не вижу, и мое (возможно, ошибочное) понимание глобальных переменных упирается в стену.

Любая помощь будет очень признательна. Спасибо.

Джефф

Код:


/***************************************************
  Copper Plating Tank Control - v1.1
  by Jeff W. Parisse - July 7st, 2021
  www.coppercholla.com

  This program runs a programmable interval timer for chemical pump
  duty cycle and a programmable temperature setting and heating control
  for maintaining plating solution temperature.

  Processor: PJRC Teensy 3.2
  Additional Libraries: Adafruit Industries LLC
  Temperature Sensor: Adafruit MAX31865 w/P1000 Platinum Wire Probe
  Pin Outs:
    Setting Knob: Pin A0
    Matrix Display: Feather Matrix I2C 0x70
    Neopixels: Pin 5
    MAX31865: CLK Blue
    MAX31865: SDO Yellow
    MAX31865: SDI White
    MAX31865: CS Pin 6 Green
    Temp Set Switch: Pin 8
    Chemical Pump: Pin 9
    Tank Heater: Pin 10

 ****************************************************/

#include <Adafruit_MAX31865.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
#include <Adafruit_NeoPixel.h>

#define knobPin A0
#define ledPin 5
#define csPin 6
#define switchPin 8
#define pumpPin 9
#define heaterPin 10
#define ledCount 8
#define sampleNum 4
#define RREF      4296.0
#define RNOMINAL  1000.0

Adafruit_MAX31865 thermo = Adafruit_MAX31865(csPin);
Adafruit_7segment matrix = Adafruit_7segment();
Adafruit_NeoPixel strip(ledCount, ledPin, NEO_GRB + NEO_KHZ800);

float targetTemp = 77.0;                // Starting Value
float readTemp = 0;
float toleranceTemp = 0.25;
float tempSum = 0;
float cTemp = 0;
float fTemp = 0;
volatile float dutyCycle = 4;
unsigned long previousTime = 0;
unsigned long oneHour = 3600000;       // 1 Hour in Milliseconds
unsigned long timeOn = 450000;         // 7.5 Minutes in Milliseconds
unsigned long pumpInterval = timeOn;
boolean pumpState = true;

void setup() {
  thermo.begin(MAX31865_3WIRE);;
  matrix.begin(0x70);
  strip.begin();
  strip.show();
  pinMode(csPin, OUTPUT);
  pinMode(heaterPin, OUTPUT);
  pinMode(pumpPin, OUTPUT);
  pinMode(switchPin, INPUT_PULLUP);
  digitalWrite(csPin, LOW);
  digitalWrite(heaterPin, LOW);
  digitalWrite(pumpPin, LOW);
}

void loop() {
  // Read Set Switch
  int setSwitch = (digitalRead(switchPin));
  while (setSwitch == LOW) {
    int readKnob = analogRead(knobPin);
    targetTemp = map(readKnob, 1, 1023, 67, 87);
    matrix.print(targetTemp, 1);
    matrix.writeDisplay();
    setSwitch = (digitalRead(switchPin));
  }

  // Read, Convert, and Display Temp
  tempSum = 0;
  for (int i = 1; i <= sampleNum; i++) {
    readTemp = thermo.temperature(RNOMINAL, RREF);
    tempSum = tempSum + readTemp;
  }
  cTemp = tempSum / sampleNum;
  fTemp = (cTemp * 1.8) + 32;
  matrix.print(fTemp, 1);
  matrix.writeDisplay();

  // Heater Logic
  if (fTemp < targetTemp - toleranceTemp) {
    digitalWrite(heaterPin, HIGH);
  }
  else if (fTemp > targetTemp + toleranceTemp) {
    digitalWrite(heaterPin, LOW);
  }

  // Read and Display Duty Cycle
  int readKnob = analogRead(knobPin);
  dutyCycle = map(readKnob, 1, 1023, 1, 8);
  for (int i = 0; i <= ledCount; i++) {
    strip.setPixelColor(i, 0, 0, 0);
  }
  strip.show();
  for (int i = 0; i <= dutyCycle - 1; i++) {
    strip.setPixelColor(i, 0, 0, 20);
  }
  strip.show();

  // Pump Timer
  digitalWrite(pumpPin, pumpState);
  unsigned long timeOn = ((dutyCycle / 8UL) * oneHour);
  unsigned long timeOff = (oneHour - timeOn);
  unsigned long currentTime = millis();
  if (currentTime - previousTime >= pumpInterval) {
    if (pumpState) {
      pumpInterval = timeOff;
    }
    else {
      pumpInterval = timeOn;
    }
    pumpState = !(pumpState);
    previousTime = currentTime;
  }
}

, 👍2

Обсуждение

Вы пробовали распечатать и протестировать для вывода функции карты?, @fabiuz7

И почему это значение с плавающей точкой, если его значение может быть только целым числом от 1 до 8?, @Dave Newton


1 ответ


2

Я действительно не понимаю, в чем может быть причина вашей проблемы, но я определил две проблемы, которые потенциально могут быть связаны.

У вас есть:

dutyCycle = map(readKnob, 1, 1023, 1, 8);

Из-за некоторых проблем с округлением в функции Arduino map() это может работать не так, как вы ожидаете: выход будет равен 8, только если вход достигнет 1023. Если readKnob равен 1022, то DutyCycle будет равен 7. Это может объяснить, почему вы никогда не видите, что насос постоянно включен.

Способ работы map() имеет наибольший смысл, если вы мыслите в терминах полуоткрытых интервалов, открытых справа. Если вы напишете:

dutyCycle = map(readKnob, 0, 1024, 1, 9);

вы получите идеальное отображение от [0, 1024) до [1, 9). Идеально в том смысле, что каждому выходному значению будет сопоставлено ровно 128 входных значений:

[  0, 128) → 1
[128, 256) → 2
[256, 384) → 3
...

И позже:

for (int i = 0; i <= ledCount; i++) {
    strip.setPixelColor(i, 0, 0, 0);
}

Полоса имеет количество пикселей светодиодов, пронумерованных от 0 до 1. Этот цикл установит цвет пикселей от 0 до ledCount включительно. Последняя итерация выходит за пределы конца полосы, и это, скорее всего, приводит к повреждению памяти, т. Е. перезаписи любых данных, которые находятся сразу после области памяти, используемой для полосы. Если это перезапись какой -то переменной, связанной с рабочим циклом, это может объяснить странное поведение , которое вы испытываете.

,

Спасибо, Эдгар… Я перепишу это после обеда и обратной связи…, @Jeff Parisse

Фабиан... сначала я так и сделал, когда работал с маршрутизацией светодиодов. Затем я перестал следить за этой функцией… вероятно, поэтому я, возможно, пропустил это., @Jeff Parisse

Дейв, потому что я хватался за соломинку, а не делал то, что делаю сейчас, просил о помощи, что гораздо более рационально… Я исправлю этот код как можно скорее. :-), @Jeff Parisse