Помогите совместить цифровой и аналоговый код в программировании ардуино

Итак, я делаю устройство, которое делает 3 вещи:

  1. Измеряет частоту звукового сигнала через микрофон.
  2. Проверяет, есть ли груз на прижимной подушке (мой датчик давления работает за счет изменения сопротивления материала, когда на него помещается груз)
  3. Измерение температуры окружающей среды в помещении.

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

Скетч частоты:

// выполняется каждый раз в цикле
  setInputState();

  // считаем каждый переход HIGH<->LOW
  if (inputState != lastInputState) {
    count++;  
    lastInputState = inputState;
  }

  if (millis() - previousCountMillis >= countMillis) {
    previousCountMillis += countMillis;

    // показываем Гц и на Serial, если доступно
    Serial.print(count); 
    Serial.println(" Hz");
    ledtest = count;
    // сбрасываем в ноль для выборки следующей полсекунды
    count = 0L;
  }
  if (ledtest >= 400 && ledtest <= 850){
    digitalWrite(A2, HIGH);
  }
  else if (ledtest < 400 || ledtest > 850){
    digitalWrite(A2, LOW);
  }
}

Вот скетч датчика давления

int Vin = 5;
float Vout = 0;
float raw1 = 0;

int R1 = 770;

int R2old1 = 0;

int R2new1 = 0;

int R2avg1 = 0;

int pressurelog = 0;

void setup() {
  pinMode(A0, INPUT);             //Получить напряжение давления
  pinMode(A1, OUTPUT);            //Красный светодиод, НАЖИМНАЯ ПОДУШКА
}

void loop() {
  raw1 = analogRead(A0);
  Vout = raw1*5/1024;
  R2old1 = Vout*R1/(Vin-Vout);

  raw1 = analogRead(A0);
  Vout = raw1*5/1024;
  R2new1 = Vout*R1/(Vin-Vout);

  R2avg1 = (R2new1+R2old1)/2;

  Serial.print("Resistance: ");
  Serial.println(R2avg1);

  if (R2avg1 >= 1000){
    digitalWrite(A1, LOW);
    pressurelog = 0;
  }
  else if (R2avg1 <= 1000){
    digitalWrite(A1, HIGH);
    pressurelog = 1;
  }  
}

вот температурный код

float raw = 0;
float tempC = 0;
float tempF = 0;

void setup() {
  pinMode(A5, INPUT);
  pinMode(A1, OUTPUT);
  Serial.begin(9600);
}

void loop() {
 raw = analogRead(A5) * 0.004882814;
 tempC = (raw - 0.5) * 100.0;
 tempF = (180.0/100.0)*tempC + 32.0;

 Serial.print("temp: ");
 Serial.println(tempF);
 delay(1000);
}

Я соединил «пустой цикл» всех трех, определил все и запустил код, чтобы получить своеобразный результат. Он прекрасно сообщает о температуре и давлении, но, кажется, постоянно пропускает измерение частоты. Кажется, что нужно выполнить измерение давления и температуры около 50 раз, а затем выполнить аудиоизмерение, которое не имеет смысла, поскольку оно должно делать это последовательно.

Я ПЫТАЛСЯ:

  1. Добавление задержки между измерением частоты и двумя другими. Это не сработало, так как теперь работает измерение звука, так как оно зависит от функции millis()
  2. добавление 3 компонентов в 3 разные функции и их последовательный вызов. Это приводит к точно такому же глупому выводу.

Есть ли у кого-нибудь идея или решение?

Combined code: 

int Vin = 5;
float Vout = 0;
float raw1 = 0;

int R1 = 770;

int R2old1 = 0;

int R2new1 = 0;

int R2avg1 = 0;

int pressurelog = 0;



const byte inputPin = 2;

boolean inputState = false;
boolean lastInputState = false;
long count = 0L;
int ledtest = 0L;

unsigned long previousCountMillis = millis();
const long countMillis = 500L;

void setInputState() {
  inputState = digitalRead(inputPin);
}

int crylog = 0;



float raw = 0;
float tempC = 0;
float tempF = 0;

int templog = 0;

void setup() {
  pinMode(inputPin, INPUT);       //Получить данные микрофона
  pinMode(A0, INPUT);             //Получить напряжение давления
  pinMode(A1, OUTPUT);            //Красный светодиод, НАЖИМНАЯ ПОДУШКА
  pinMode(A2, OUTPUT);            //Синий светодиод, ЧАСТОТА/ПЛАЧ
  pinMode(A3, OUTPUT);            //Зеленый светодиод, ТЕМПЕРАТУРА
  pinMode(A4, OUTPUT);            //Красный светодиод, МАКС. ПРЕДУПРЕЖДЕНИЕ
  Serial.begin(115200);
}

void loop() {
  Serial.println("HI");
  Cryometer();
  delay(2);
  Serial.println("YO");
  Pressure();
  Temperature();

  // НАСТРОЙКА ПРЕДУПРЕЖДЕНИЯ
  if (pressurelog == 1 && templog == 1){
    digitalWrite(A4, HIGH);
  }
  else {
    digitalWrite(A4, LOW);
  }
}

void Pressure() {
  raw1 = analogRead(A0);
  Vout = raw1*5/1024;
  R2old1 = Vout*R1/(Vin-Vout);

  raw1 = analogRead(A0);
  Vout = raw1*5/1024;
  R2new1 = Vout*R1/(Vin-Vout);

  R2avg1 = (R2new1+R2old1)/2;

  Serial.print("Resistance: ");
  Serial.println(R2avg1);

  if (R2avg1 >= 1000){
    digitalWrite(A1, LOW);
    pressurelog = 0;
  }
  else if (R2avg1 <= 1000){
    digitalWrite(A1, HIGH);
    pressurelog = 1;
  }  
}

void Cryometer(){
  // выполняется каждый раз через цикл
  setInputState();

  // считаем каждый переход HIGH<->LOW
  if (inputState != lastInputState) {
    count++;  
    lastInputState = inputState;
  }

  if (millis() - previousCountMillis >= countMillis) {
    previousCountMillis += countMillis;

    // показываем Гц и на Serial, если доступно
    Serial.print("Frequency: ");
    Serial.print(count); 
    Serial.println(" Hz");
    ledtest = count;
    // сбрасываем в ноль для выборки следующей полсекунды
    count = 0L;
  }
  if (ledtest >= 400 && ledtest <= 850){
    digitalWrite(A2, HIGH);
    crylog = 1;
  }
  else if (ledtest < 400 || ledtest > 850){
    digitalWrite(A2, LOW);
    crylog = 0;
  }  
}

void Temperature() {
   raw = analogRead(A5) * 0.004882814;
   tempC = (raw - 0.5) * 100.0;
   tempF = (180.0/100.0)*tempC + 32.0;

   Serial.print("Temperature (F): ");
   Serial.println(tempF);
   Serial.println();

  if (tempF >= 75 && ledtest <= 50){
    digitalWrite(A3, HIGH);
    templog = 1;
  }
  else if (ledtest < 50 || ledtest > 75){
    digitalWrite(A3, LOW);
    templog = 0;
  }
}

, 👍1

Обсуждение

Так опубликуйте свой комбинированный код. Вам также необходимо объединить функции setup() и убедиться, что у вас нет конфликтов контактов (аппаратное обеспечение) или конфликтов имен с вашими именами переменных (программное обеспечение)., @Duncan C

Извините, забыл комбинированный код, но чтобы ответить на остальную часть вашего сообщения; Я сделал все это и убедился, что он должен работать идеально, он, кажется, отлично выполняет частотный анализ, но по какой-то причине просто не хочет делать это с каждым циклом выполнения давления и температуры., @collproj


1 ответ


1

Ваш подход является общепринятым. Однако код, измеряющий входная частота очень чувствительна ко времени. Таким образом, вы должны убедиться, что это кусок кода никогда не задерживается ничем другим. Это значит, что все в вашем скетче должно быть быстрым и неблокирующим.

Я вижу несколько примеров блокирующего поведения, от которых следует избавиться: вызов delay() и последовательный вывод. Первое особенно бесполезно, так что просто удалите его. Печать на последовательный порт выполняется нормально, пока поскольку вы не пытаетесь напечатать слишком много. Если вы попытаетесь печатать в каждом цикле итерации, вы в конечном итоге заполните выходной буфер. Оттуда каждый print становится блокирующим вызовом: последовательная библиотека должна ждать порт для отправки данных, пока в буфере не будет достаточно места для что вы хотите отправить. Решение состоит в том, чтобы снизить скорость вывода печатая только время от времени. Вы сделали это блестяще в код частотомера:

if (millis() - previousCountMillis >= countMillis) {
  previousCountMillis += countMillis;
  Serial.print("Frequency: ");
  Serial.print(count); 
  Serial.println(" Hz");
  // ...
}

Теперь вам просто нужно применить один и тот же метод к каждому экземпляру Serial.print() и Serial.println(). Ну, может быть, "привет" "йо" может просто удалить вместо этого...

После того как вы уберете из скетча эти блокирующие функции, он вероятно, работает достаточно быстро, чтобы подсчет частоты выполнялся правильно. Однако есть еще кое-что, что вы, возможно, захотите оптимизировать: вычисления в Pressure() ужасно неэффективны, особенно учитывая, что у вас 8-битный процессор без аппаратной плавающей запятой поддерживать. Если вам нужно усреднить, я предлагаю вам усреднить аналог показания, а не вычисленные сопротивления. Также обратите внимание, что вычисление напряжение на аналоговом выводе совершенно бесполезно:

void Pressure() {
    int raw = analogRead(A0) + analogRead(A0);
    float R = (float) R1 * raw / (2048 - raw);
    // ...
}

Вы даже можете заменить float на long, если вам не нужно разрешение лучше 1 Ом.

,