Цифровой компаратор с 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

Обсуждение

Выходы представляют собой простую логику с последовательностью 10k в резисторах R, чтобы избежать защелкивания. L1=XNor<A,B, L2=A&!B, L3 =!A&B, @Tony Stewart Sunnyskyguy EE75

«Я убрал резисторы со светодиодов, чтобы сделать их меньше». - Ваш комментарий относится к _схеме_, а не к готовой схеме, верно?, @JRobert

Да, это всего лишь схема. Я заметил плохую формулировку, но не стал ее редактировать., @Tvde1


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 мс перед считыванием ваших цифровых входов, чтобы позволить пользователю изменить состояние этих цифровых входов.

,

Это не решает проблему. Сброс ATTiny равносилен зацикливанию и выключению всего остального., @Tvde1

Ну, я бы использовал его только в течение короткого периода времени., @Tvde1

Да, вручную, отключив и подключив, @Tvde1

Это основная часть ответа, но вам нужно *объяснить*, что не так, а не просто предоставить кучу альтернативного кода без объяснений., @Chris Stratton


0

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

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

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

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

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

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

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

,

Хм, спасибо, я улучшу это с помощью цикла или прерываний при изменении напряжения., @Tvde1

не начинайте думать о прерываниях, пока не научитесь писать базовый код, @jsotola

Хотя это и не совсем ложно, это не решает вопиющую проблему кода, а только косвенную неудачу в достижении чистого сброса при включении питания, когда входы питают чип. Если бы код был правильным, эта теоретическая проблема не наблюдалась бы на практике., @Chris Stratton

Почему код не верный? Я не вижу в этом проблемы., @Tvde1

Да, но я стремился к низкому энергопотреблению, поскольку мне не нужно было часто его запускать, и я решил, что могу включать его только тогда, когда мне нужно, чтобы он выдавал данные., @Tvde1


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 в спящий режим и выведите его из спящего режима. на прерывании смены пина. Но убедитесь, что у вас есть простая версия Сначала работайте, а потом уже беспокойтесь об экономии энергии и режимах сна.

,