Цифровой компаратор с ATTiny85 ведет себя не так, как ожидалось

Вот моя схема:

Я убрал резисторы со светодиодов, чтобы сделать их меньше. 1 и 2 слева — это выходы Arduino (которая подает VCC и землю).

Эти 1 и 2 — HIGH или LOW, и я хочу, чтобы светодиоды включались в соответствии с этой таблицей:

┌───────┬────────────────────┐
│ INPUT │ OUTPUT             │
├───┬───┼──────┬──────┬──────┤
│ A │ B │ Led1 │ Led2 │ Led3 │
├───┼───┼──────┼──────┼──────┤
│ 0 │ 0 │ 1    │ 0    │ 0    │
│ 1 │ 0 │ 0    │ 1    │ 0    │
│ 0 │ 1 │ 0    │ 0    │ 1    │
│ 1 │ 1 │ 1    │ 0    │ 0    │
└───┴───┴──────┴──────┴──────┘

А это код, который я использую с ATTiny85

const int pinA = PB3;
const int pinB = PB4;
const int pinOut1 = PB2;
const int pinOut2 = PB1;
const int pinOut3 = PB0;

void setup() {
    pinMode(pinA, INPUT);
    pinMode(pinB, INPUT);
    pinMode(pinOut1, OUTPUT);
    pinMode(pinOut2, OUTPUT);
    pinMode(pinOut3, OUTPUT);

    int a = digitalRead(pinA);
    int b = digitalRead(pinB);

    if (a == b) {
        digitalWrite(pinOut3, HIGH);
    }
    else if (a == HIGH) {
        digitalWrite(pinOut1, HIGH);
    }
    else {
        digitalWrite(pinOut2, HIGH);
    }
}

При такой настройке я получаю следующий результат:

┌───────┬────────────────────┐
│ INPUT │ OUTPUT             │
├───┬───┼──────┬──────┬──────┤
│ A │ B │ Led1 │ Led2 │ Led3 │
├───┼───┼──────┼──────┼──────┤
│ 0 │ 0 │ 1    │ 0    │ 0    │
│ 1 │ 0 │ 0    │ 1    │ 0    │
│ 0 │ 1 │ 1    │ 0    │ 0    │ <- Увидьте разницу
│ 1 │ 1 │ 1    │ 0    │ 0    │
└───┴───┴──────┴──────┴──────┘

Я думаю, это как-то связано с тем, что ATTiny включается, если подать 5 В на один из входных контактов, а не на VCC.

И да, я постоянно перезапускаю плату (вытаскивая контакт VCC и наблюдая, как гаснет светодиод).

Я также пробовал подключать A и B к VCC и заземлению во всех возможных положениях. Здесь я заметил, что подключение A (или B) к 5v (arduino) при неподключенном VCC, плата включится .

Надеюсь, этой информации достаточно.

, 👍0


3 ответа


2

Вы должны назначить статус всех выходных контактов в каждом из условий вашего "if statement". Думайте об этом как о "если это произойдет, я хочу, чтобы x, y, & z были включены, а a, b, & c были выключены". Неизменение статуса HIGH одного выхода сохранит этот выход HIGH для всех условий. Выходные контакты никогда не изменят свои статусы, пока у них не будет приказа "ваш код" сделать это. Также вам нужно заменить свой код внутри функции цикла, чтобы повторить ваш код без необходимости вручную сбрасывать ваш ATTiny.

Предполагая, что LED1 = контакт Out1, LED2 = контакт Out2, LED3 = контакт Out3. Вам необходимо заменить «условия if» в вашем коде следующим:

while( 1 ){
    int a = digitalRead(PinA);
    int b = digitalRead(PinB);

    if ( a == b ) {
        digitalwrite (pinOut1 , HIGH);
        digitalwrite(pinOut2,LOW) ;
        digitalwrite (pinOut3, LOW);
    }
    else if ( a == HIGH ) {
        digitalwrite(pinOut2,HIGH) ;
        digitalwrite(pinOut1,LOW) ;
        digitalwrite(pinOut3,LOW);
    }
    else if ( b == HIGH ) {
        digitalwrite(pinOut3,HIGH) ;
        digitalwrite(pinOut1,LOW) ;
    digitalwrite(pinOut2,LOW);
    }
}

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

,

0

Я думаю, это как-то связано с тем, что ATTiny включается, если подать 5 В на один из входных контактов, а не на VCC.

И да, я постоянно перезапускаю плату (вытаскивая контакт VCC и наблюдая, как гаснет светодиод).

Здесь я заметил, что при подключении A (или B) к 5 В (Arduino), когда VCC не подключен, плата включится.

Все вышесказанное можно примерно перевести как «Я жарю чипсы и не знаю, почему они не работают».

Посмотрите на «абсолютные максимальные рейтинги» в техническом описании:

"Напряжение на любом выводе, кроме RESET, относительно земли от -0,5 В до VCC+0,5 В"

Короче говоря, вам нужно включить MCU перед подачей напряжения на входные контакты. Вот почему так удивительно, что у вас нет цикла в main().

,

1

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

  1. выключите и включите ATtiny
  2. установить его вход A на НИЗКИЙ
  3. установите его вход B на HIGH.

ATtiny вполне может считывать свои входные данные прямо между шагами 2 и 3 выше. Затем он увидит оба входа LOW и сделает то, что должен предполагается, что в этом случае это будет сделано. Это называется состоянием гонки, и обычно приводит к ошибкам, которые очень трудно обнаружить.

Правильный способ использования этой конкретной программы — никогда не удалять ее. мощность и:

  1. установить новые входы
  2. подайте импульс на вывод RESET ATtiny LOW на несколько микросекунд.

Конечно, было бы гораздо лучше иметь разумный дизайн, который не заставить вас сделать сброс. См. ответ Ахмеда М. Захрана. Для такого рода тривиальная задача (просто реализация таблицы истинности) Я предпочитаю реализовать решение на чистом языке C:

#include <avr/io.h>

static const uint8_t truth_table[] = {1, 2, 4, 1};

int main(void)
{
    DDRB = 0x7;  // PB0..PB2 как выходы
    for (;;) {
        uint8_t input = (PINB >> 3) & 0x3;  // 2 входных бита
        PORTB = truth_table[input];  // отправка выходных данных на светодиоды
    }
}

Если вы беспокоитесь о питании, переведите ATtiny в спящий режим и выведите его из спящего режима. на прерывании смены пина. Но убедитесь, что у вас есть простая версия Сначала работайте, а потом уже беспокойтесь об экономии энергии и режимах сна.

,