analogRead на attiny85

Xrou
Offline
Зарегистрирован: 10.06.2021

Всем привет, пытаюсь считывать данные с энкодера на "attiny85 uno mini usb". Как я понял, это тот же digispark. Или attiny с обвязкой и контактами под пины

Суть такая. Ардуино запрашивает с attiny какое-то значение по i2c. attiny принимает запрос и отправляет значение с одного из аналоговых входов. Но вместо меняющегося значения все время прилетает 255.

#код для аттини
#include <TinyWireS.h>

byte i2c_rcv = 0;
int potVal;

uint8_t pin = 0;

void setup()
{
  TinyWireS.begin(0x0F);
  pinMode(1, OUTPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  TinyWireS.onRequest(angleRequest);

  digitalWrite(1, HIGH);
  delay(20);
  digitalWrite(1, LOW);
}

void loop()
{

}

void angleRequest()
{
  if (pin == 0)
  {
    potVal = analogRead(0);
    pin = 1;
  }
  else if (pin == 1)
  {
    potVal = analogRead(1);
    pin = 2;
  }
  else if (pin == 2)
  {
    potVal = analogRead(2);
    pin = 3;
  }
  else if (pin == 3)
  {
    potVal = analogRead(3);
    pin = 0;
  }
  

  TinyWireS.send(potVal);

  digitalWrite(1, HIGH);
  delay(500);
  digitalWrite(1, LOW);
}

 

# ардуино
#include <Wire.h>

void setup() 
{
  Wire.begin();
  Serial.begin(9600);
  
  pinMode(13, OUTPUT);
  
  digitalWrite(13, HIGH);
  delay(20);
  digitalWrite(13, LOW);
}

void loop() 
{
  Wire.requestFrom(0x0F, 4);

  while (Wire.available())
  {
    Serial.print("angle = ");
    Serial.println(Wire.read());
  }
  
  delay(200);
}

Множество раз слышал о важности фьюз битов и analogReference, но так и не понял как это применять на attiny.

Подскажите как заставить это работать, сам не понимаю, что не так.

Туториал брал тут - http://digistump.com/wiki/digispark/tutorials/basics
Плата в настройках arduino ide - "Digistump AVR boards -> Digispark (default 16.5MHz)"

Alexey_Rem
Offline
Зарегистрирован: 09.09.2019

 А как данные с энкодера читаются функцией analogRead()?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

1. Оформлено все в функцию, но где же вызов этой самой функции?

2. Работы с энкодером вообще нет. И откуда у него вообще 4 вывода?! 
3 Приложите схему соединений. 
4. Зачеты и курсовые прошли вроде бы...

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Энкодер != потенциометр.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Мне больше интересно как его (энкодер) аж на 4 пина разнесло ))) Да и потенциометр обычно только три пина имеет  и их просто к пинам тини подключать как-то глупо чтоле...

ЗЫ: Вызов функции увидел, но она только один раз вызывается. Или так и должно быть? Я просто этот момент не знаю. 

b707
Онлайн
Зарегистрирован: 26.05.2017

BOOM пишет:

Вызов функции увидел, но она только один раз вызывается.

это колбек, функция отрабатывается при поступление запроса по Wire

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

Ну и очень интересн вопрос , что это за энкодер такой, который читается с аналоговых пинов

Xrou
Offline
Зарегистрирован: 10.06.2021

b707 пишет:

это колбек, функция отрабатывается при поступление запроса по Wire

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

Ну и очень интересн вопрос , что это за энкодер такой, который читается с аналоговых пинов

Перепутал, не энкодер, а потенциометр. (энкодер цифровой, потенциометр аналоговый). Почему отсылается 2? Смотрел по сайту https://docs.microsoft.com/ru-ru/cpp/cpp/data-type-ranges?view=msvc-160&viewFallbackFrom=vs-2019 тут написано, что инт - 4 байта.

 

BOOM пишет:

Мне больше интересно как его (энкодер) аж на 4 пина разнесло ))) Да и потенциометр обычно только три пина имеет  и их просто к пинам тини подключать как-то глупо чтоле...

ЗЫ: Вызов функции увидел, но она только один раз вызывается. Или так и должно быть? Я просто этот момент не знаю. 

Я считываю уже со всех возможных пинов, что бы не было такого, что я не туда подключил что-то. А функция - это коллбек на входящий запрос по i2c как я понял. 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А не проще одеть очки (как я это делаю) и посмотреть куда же вы всё-таки подключили? Может вообще не подключили? Или мимо?))

И где схема подключения? Ах да, тут проблема на много более глобальная (простите мой сарказм, не удержался). 

Xrou
Offline
Зарегистрирован: 10.06.2021

Нет, подключил не мимо) Схему нарисовать могу только в пеинте. Digispark во фритзинге нету, скачать найти не могу

Xrou
Offline
Зарегистрирован: 10.06.2021

Схема

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Да хоть в нем. Хотя я по привычке рисую в sPlan ( http://www.cqham.ru/ftp3/sPlan_6.0.0.2_full_rus.exe )

Ну и слегка осваиваю https://easyeda.com/

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

В строке №15 (верхнего кода), Вы работаете с PB5, а в строке №32 с ADC0 (он же PB5). Ничего, что это Reset? Так и задумано?

b707
Онлайн
Зарегистрирован: 26.05.2017

Xrou пишет:

Смотрел по сайту https://docs.microsoft.com/ru-ru/cpp/cpp/data-type-ranges?view=msvc-160&viewFallbackFrom=vs-2019 тут написано, что инт - 4 байта.

какое отношение документация по Microsoft C++ имеет к Дигиспарку? Или вы не в курсе. что размер типов int float double и прочих на разных контроллерах разный?

Какой размер int на Дигиспарке? 4 байта? Уверены? На Ардуино int - 2 байта

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

b707 пишет:

Какой размер int на Дигиспарке? 4 байта? Уверены? На Ардуино int - 2 байта

Вообще-то только на 8-разрядных контроллерах Ардуино. На 32-разрядных - 4 байта. Но attiny вряд ли относится к 32-разрядным.

(кстати, меня тоже шокировала ссылка на Майкрософт применительно к Ардуино)

Xrou
Offline
Зарегистрирован: 10.06.2021

ЕвгенийП пишет:

В строке №15 (верхнего кода), Вы работаете с PB5, а в строке №32 с ADC0 (он же PB5). Ничего, что это Reset? Так и задумано?

А зачем тогда на этом пине вообще что то кроме резет? Уберу. Результат не изменяется от этого.

 

b707 пишет:

какое отношение документация по Microsoft C++ имеет к Дигиспарку? Или вы не в курсе. что размер типов int float double и прочих на разных контроллерах разный?

 

Думал это стандарт и размер везде одинаковый.

Часто когда читал про работу с attiny видел, что устанавливают какие-то ядра. Насколько сильно они важны и можно ли работать с "заводским"? Может быть проблема в нем?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Xrou пишет:

А зачем тогда на этом пине вообще что то кроме резет?

Потому, что ресет можно отключить соответствующим фьюзом (RSTDISBL) - тогда его там не будет и пином можно будет пользоваться по остальным его назначениям.

Только не пытайтесь это сделать, если у Вас нет высоковольтного программатора. Без ресета обычным программатором прошить МК будет невозможно и Вам придётся либо покупать весьма недешёвый высоковольтный программатор, либо выбрасывать МК.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Xrou пишет:
Может быть проблема в нем?
Проблема в том, что у Вас полная мешанина в коде.

Кроме использования Reset, наблюдается, например, такая забавная штука: в строке №37 Вы используете ADC1. Прекрасно, но это пин PB2, который у Вас на самом деле занят библиотекой TinyWireS

Как Вы это всё подключали? Вы не видели, что на одни и те же пины разные вещи цепляли? Или в Вашем аддоне другая распиновка и я тут чушь несу?

Давайте-ка схему подключения и и точно скажите что за аддон у Вас.

Xrou
Offline
Зарегистрирован: 10.06.2021

void setup()
{
  pinMode(1, OUTPUT);
  pinMode(3, INPUT);
}

void loop()
{
  uint16_t sensorValue = analogRead(3);
  
  analogWrite(1, sensorValue >> 2);
}

Собрал вот так. Работает. Значит дело не в том, что "что-то не читается", а в i2c скорее всего. Сейчас исправлю, выложу результат 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Xrou пишет:
а в i2c скорее всего.
Так я же Вам писал, что Вы его пин заняли. Конечно, он обидится.

v258
Offline
Зарегистрирован: 25.05.2020

ЕвгенийП пишет:

Потому, что ресет можно отключить соответствующим фьюзом (RSTDISBL) - тогда его там не будет и пином можно будет пользоваться по остальным его назначениям.

Я использовал этот пин как вход АЦП. Работает. Но как только напряжение на нем опускается ниже 0,5 VCC, МК уходит в ребут. Т.е. если сильно надо, использовать можно, но нужно подбирать делитель так, чтобы напряжение всегда было в пределах допустимого

b707
Онлайн
Зарегистрирован: 26.05.2017

Xrou пишет:

Часто когда читал про работу с attiny видел, что устанавливают какие-то ядра. Насколько сильно они важны и можно ли работать с "заводским"? Может быть проблема в нем?

каким "заводским"? Насколько я знаю, свежеустановленная Ардуино ИДЕ с аттини не работает вообще, в любом случае надо устанавливать пакет поддержки. Вы какой ставили - укажите ссылку.

Xrou
Offline
Зарегистрирован: 10.06.2021

b707 пишет:

Xrou пишет:

Часто когда читал про работу с attiny видел, что устанавливают какие-то ядра. Насколько сильно они важны и можно ли работать с "заводским"? Может быть проблема в нем?

каким "заводским"? Насколько я знаю, свежеустановленная Ардуино ИДЕ с аттини не работает вообще, в любом случае надо устанавливать пакет поддержки. Вы какой ставили - укажите ссылку.

http://digistump.com/package_digistump_index.json - это в разделе доп. ссылок для менеджера плат в настройках.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

v258 пишет:

Я использовал этот пин как вход АЦП.

Никогда не говорите таких вещей в подобных темах! Вы ведь говорите это в теме человека, который не отличает пин ADC От пина PWM! Одним можно одно, другим - другое ("Quod licet Iovi, non licet bovi"). ТС использовать этот пин иначе как Reset нельзя ни при каких обстоятельствах. Даже не обсуждается!

Xrou
Offline
Зарегистрирован: 10.06.2021

Xrou пишет:

Схема

Собрал еще раз эту схему. Теперь значение с P3 записывается в лупе, выводится на светодиод и отдается при запросе. 

#include <TinyWireS.h>

uint16_t potVal;

void setup()
{
  TinyWireS.begin(0x0F);
  pinMode(1, OUTPUT);
  pinMode(3, INPUT);
  TinyWireS.onRequest(angleRequest);

  digitalWrite(1, HIGH);
  delay(20);
  digitalWrite(1, LOW);
}

void loop()
{ 
  potVal = analogRead(3);
  analogWrite(1, potVal >> 2);
}

void angleRequest()
{
  TinyWireS.send(potVal);
}
#include <Wire.h>

void setup() 
{
  Wire.begin();
  Serial.begin(9600);
  
  pinMode(13, OUTPUT);
  
  digitalWrite(13, HIGH);
  delay(20);
  digitalWrite(13, LOW);
}

void loop() 
{
  Wire.requestFrom(0x0F, 2);

  while (Wire.available())
  {
    Serial.print("Potenciometer = ");
    Serial.println(Wire.read());
  }
  
  delay(200);
}

Теперь запрашиваю 2 байта и отдаю столько же. Приходит 255. Посмотрел анализатором, там тоже 255. Какие еще варианты есть?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Xrou пишет:
Какие еще варианты есть?

Даже не знаю.

Может просто посмотреть на свою плату?

Что мы здесь видим?

Пины 0 и 2 заняты I2C.
Пины 3 и 4 заняты USB
Пин 5 занят Reset'ом

Что осталось? Остался только пин 1 !!!

Вот к нему и подключайте свой POT - к пину 1. И сделайте такой код

#include <TinyWireS.h>

// uint16_t potVal; // нахрен

void setup()
{
  TinyWireS.begin(0x0F);
  //pinMode(1, OUTPUT); // нахрен
  //pinMode(3, INPUT); // нахрен
  TinyWireS.onRequest(angleRequest);

  //digitalWrite(1, HIGH); // нахрен
  //delay(20); // нахрен
  //digitalWrite(1, LOW); // нахрен
}

void loop()
{
  // potVal = analogRead(3); // нахрен
  // analogWrite(1, potVal >> 2); // Это про что вообще?
}

void angleRequest()
{
  TinyWireS.send(analogRead(1));
}
Xrou
Offline
Зарегистрирован: 10.06.2021

ЕвгенийП пишет:

Xrou пишет:
Какие еще варианты есть?

Даже не знаю.

Может просто посмотреть на свою плату?

Что мы здесь видим?

Пины 0 и 2 заняты I2C.
Пины 3 и 4 заняты USB
Пин 5 занят Reset'ом

Что осталось? Остался только пин 1 !!!

Вот к нему и подключайте свой POT - к пину 1. И сделайте такой код

#include <TinyWireS.h>

// uint16_t potVal; // нахрен

void setup()
{
  TinyWireS.begin(0x0F);
  //pinMode(1, OUTPUT); // нахрен
  //pinMode(3, INPUT); // нахрен
  TinyWireS.onRequest(angleRequest);

  //digitalWrite(1, HIGH); // нахрен
  //delay(20); // нахрен
  //digitalWrite(1, LOW); // нахрен
}

void loop()
{
  // potVal = analogRead(3); // нахрен
  // analogWrite(1, potVal >> 2); // Это про что вообще?
}

void angleRequest()
{
  TinyWireS.send(analogRead(1));
}

 

Не, может я чего не понимаю если речь про пин P1 - то там ацп вообще нет. Да и мне не только потенциометр надо подключить сюда, еще и серву. Нельзя что-ли? 

v258
Offline
Зарегистрирован: 25.05.2020

Xrou пишет:

Не, может я чего не понимаю если речь про пин P1 - то там ацп вообще нет. Да и мне не только потенциометр надо подключить сюда, еще и серву. Нельзя что-ли? 

Нельзя. Но если очень хочется, то можно. Но работать скорее всего не будет ))

Xrou
Offline
Зарегистрирован: 10.06.2021

А почему не должно работать? Я ведь смог без проблем считать значение потенциометра с ноги P3. Возникли проблемы с передачей теперь уже. А серву буду подключать к P1.

Еще закрались сомнения по поводу библиотеки TinyWire. В первый раз наткнулся на видимо старую версию в которой не было даже onRequest, поставил другую. Может тут проблемы с передачей 

Xrou
Offline
Зарегистрирован: 10.06.2021

Xrou пишет:

Еще закрались сомнения по поводу библиотеки TinyWire. В первый раз наткнулся на видимо старую версию в которой не было даже onRequest, поставил другую. Может тут проблемы с передачей 

 

#include <TinyWireS.h>

int sendNumber = 0;

void setup()
{
  TinyWireS.begin(0x0F);
  TinyWireS.onRequest(angleRequest);
}

void loop()
{

}

void angleRequest()
{
  TinyWireS.send(sendNumber);
  sendNumber++;
}

Не передает. А ардуинки второй нет проверить, может это принимает неправильно

Xrou
Offline
Зарегистрирован: 10.06.2021

Интересная информация. В callback функцию программа вообще не заходила. Просто добавил моргание светодиодиком и проблема вскрылась. Скачал другую библиотеку https://github.com/lucullusTheOnly/TinyWire - заработало.

И еще вопрос. Очень часто вижу программы для мк написанные не привычным кодом, а скорее байтами. Вот что-то такое (код просто скопировал с какого-то форума)

ISR(TIMER1_COMPB_vect)            // Отработчик Timer1 прерывание по сравнению с регистром OC1B
{
    static uint8_t dimming_1_pulse=0;

    if(dimming_1_pulse)
    {
      PORTB &= ~( 1 << AC_LOAD_1 );            // Выключим оптопару
      dimming_1_pulse=0;
    }
    else
    {
      if ( dimming_1_cur < MAX_TCNT_VAL && Errflag==0 )    // Если уровень диммирования больше минимального и нет ошибки от  zero cross detect
      {
        PORTB |= ( 1 << AC_LOAD_1 );                   // Включение нагрузки 1
        OCR1B=OCR1B+PULS_COUNT;
        dimming_1_pulse=1;
      }
    }
}

ISR(TIMER1_OVF_vect)             // Обработчик Таймер 1 переполнение. Что то пошло не так, возможно не работает zero cross detection или нет напряжения сети
{
    PORTB &= ~( 1 << AC_LOAD_0 );            // Выключим нагрузку 1
    PORTB &= ~( 1 << AC_LOAD_1 );            // Выключим нагрузку 2
    Errflag=1;                               // взведем флаг ошибки в работе zero cross detect.
}

Как люди его пишут? Есть ли смысл вообще в таком низкоуровневом программировании? Как мне кажется такой код намного эффективнее работает и нет зависимости от левых библиотечек. Но в гуглах я не нахожу как такое писать, что куда пихать и сдвигать. Часто вижу такой код для STM. Возможно для понимающих он читается легко, но для меня это дремучий лес, хотя довольно много кодю.

sadman41
Offline
Зарегистрирован: 19.10.2016

Смотря что считать эффективностью. Критерии пока что не определены.

Работать этот код будет быстрее. Заметит ли кто-либо этот факт - вопрос. Но он немедленно станет платформозависимым. И сложным в понимании. И времени на его написание больше уйдёт.

b707
Онлайн
Зарегистрирован: 26.05.2017

Xrou пишет:

Как мне кажется такой код намного эффективнее работает и нет зависимости от левых библиотечек.

если вы отказываетесь  "от левых библиотек" - это означает что все их функции вам придется писать самому с нуля, а это зачастую тысячи строк. Сдюжите ли? :)

Да и времени на это уйдет ... 

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Xrou пишет:

Не, может я чего не понимаю если речь про пин P1 - то там ацп вообще нет. 

Виноват, не глянул.

Xrou пишет:

мне не только потенциометр надо подключить сюда, еще и серву. Нельзя что-ли? 

Можно. Только работать толком не будет :-(

Xrou пишет:

Как люди его пишут?

Молча. Ну, или напевая - кто как.

Xrou пишет:

Есть ли смысл вообще в таком низкоуровневом программировании?

Есть.

Xrou пишет:

Как мне кажется 

Перекреститесь :-)
wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Xrou пишет:
но для меня это дремучий лес, хотя довольно много кодю.

Стоит попробовать перестать гадить кодить и начать программировать!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

wdrakula пишет:

Стоит попробовать перестать гадить кодить и начать программировать!

Вот истину глаголешь!