analogRead на attiny85

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

#код для аттини
#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);
}

attiny подключается к ардуино по i2c, и уже ардуино печатает в serial то, что приходит

# ардуино
#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("Potenciometer = ");
    Serial.println(Wire.read());
  }
  
  delay(200);
}

Все, что мне приходит - это 255. Какое бы не было напряжение на входе. Слышал про analogReference, но так и не понял какое значение туда нужно выствлять

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

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

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

pinMode(1, OUTPUT);
analogRead(1);

ничё не попутал?

нет. В статье написано, что нумерация пинов для analogRead не такая как написано на плате

мы не про плату говорим. в коде ты указал 1 пин порта как выход, а потом считываешь его как вход. или там сказано, что если считываешь аналог, то надо писать не номер выхода порта, а ножку микросхемы?

MicroCore requires you to refer to analog pins like so: analogRead(A3);. The compiler will throw an error if you use the digital pin number instead. If you're storing the analog pin number as a variable, you'll have to use the analog_pin_t typedef or #define

ты сам не понял, что хочешь делатью
покажи, что за энкодер.

Энкодер я спутал с потенциометром.
Зачем мне схема attiny13 если у меня attiny85 на плате?

выноска из оффициальных примеров digistump

    //sensorValue = analogRead(1); //Read P2
    //To set to input: pinMode(2, INPUT);
    //THIS IS P2, P2 is analog input 1, so when you are using analog read, you refer to it as 1.

    //sensorValue = analogRead(2); //Read P4
    //To set to input: pinMode(4, INPUT);
    //THIS IS P4, P4 is analog input 2, so when you are using analog read, you refer to it as 2.

    //sensorValue = analogRead(3); //Read P3
    //To set to input: pinMode(3, INPUT);
    //THIS IS P3, P3 is analog input 3, so when you are using analog read, you refer to it as 3.

    //sensorValue = analogRead(0); //Read P5
    //To set to input: pinMode(5, INPUT);
    //THIS IS P5, P5 is analog input 0, so when you are using analog read, you refer to it as 0.

найди два отличия:

у тебя оказывается ядро digistump, ты этого не сказал.

сделай новый скетч и схему, чтобы потик считывался и выводился на светодиод как ШИМ.
проверим как считывает без I²C.

#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);
}

Светодиод меняет яркость, но передается все равно 255

А откуда библиотека TinyWireS.h?
Кажется, там нет метода send().

class USI_TWI_S
{
  private:
	//static uint8_t USI_BytesAvail;
	
  public:
 	USI_TWI_S();
    void begin(uint8_t I2C_SLAVE_ADDR);
    void send(uint8_t data);
    uint8_t available();
    uint8_t receive();
    void onReceive( void (*)(uint8_t) );
    void onRequest( void (*)(void) );
};
/**
 * Example sketch for writing to and reading from a slave in transactional manner
 *
 * NOTE: You must not use delay() or I2C communications will fail, use tws_delay() instead (or preferably some smarter timing system)
 *
 * On write the first byte received is considered the register addres to modify/read
 * On each byte sent or read the register address is incremented (and it will loop back to 0)
 *
 * You can try this with the Arduino I2C REPL sketch at https://github.com/rambo/I2C/blob/master/examples/i2crepl/i2crepl.ino 
 * If you have bus-pirate remember that the older revisions do not like the slave streching the clock, this leads to all sorts of weird behaviour
 *
 * To read third value (register number 2 since counting starts at 0) send "[ 8 2 [ 9 r ]", value read should be 0xBE
 * If you then send "[ 9 r r r ]" you should get 0xEF 0xDE 0xAD as response (demonstrating the register counter looping back to zero)
 *
 * You need to have at least 8MHz clock on the ATTiny for this to work (and in fact I have so far tested it only on ATTiny85 @8MHz using internal oscillator)
 * Remember to "Burn bootloader" to make sure your chip is in correct mode 
 */


/**
 * Pin notes by Suovula, see also http://hlt.media.mit.edu/?p=1229
 *
 * DIP and SOIC have same pinout, however the SOIC chips are much cheaper, especially if you buy more than 5 at a time
 * For nice breakout boards see https://github.com/rambo/attiny_boards
 *
 * Basically the arduino pin numbers map directly to the PORTB bit numbers.
 *
// I2C
arduino pin 0 = not(OC1A) = PORTB <- _BV(0) = SOIC pin 5 (I2C SDA, PWM)
arduino pin 2 =           = PORTB <- _BV(2) = SOIC pin 7 (I2C SCL, Analog 1)
// Timer1 -> PWM
arduino pin 1 =     OC1A  = PORTB <- _BV(1) = SOIC pin 6 (PWM)
arduino pin 3 = not(OC1B) = PORTB <- _BV(3) = SOIC pin 2 (Analog 3)
arduino pin 4 =     OC1B  = PORTB <- _BV(4) = SOIC pin 3 (Analog 2)
 */
#define I2C_SLAVE_ADDRESS 0x4 // the 7-bit address (remember to change this when adapting this example)
#include <TinyWireS.h>
// The default buffer size, Can't recall the scope of defines right now
#ifndef TWI_RX_BUFFER_SIZE
#define TWI_RX_BUFFER_SIZE ( 16 )
#endif


volatile uint8_t i2c_regs[] =
{
    0xDE, 
    0xAD, 
    0xBE, 
    0xEF, 
};
// Tracks the current register pointer position
volatile byte reg_position;

/**
 * This is called for each read request we receive, never put more than one byte of data (with TinyWireS.send) to the 
 * send-buffer when using this callback
 */
void requestEvent()
{  
    TinyWireS.send(i2c_regs[reg_position]);
    // Increment the reg position on each read, and loop back to zero
    reg_position = (reg_position+1) % sizeof(i2c_regs);
}

// TODO: Either update this to use something smarter for timing or remove it alltogether
void blinkn(uint8_t blinks)
{
    digitalWrite(3, HIGH);
    while(blinks--)
    {
        digitalWrite(3, LOW);
        tws_delay(50);
        digitalWrite(3, HIGH);
        tws_delay(100);
    }
}

/**
 * The I2C data received -handler
 *
 * This needs to complete before the next incoming transaction (start, data, restart/stop) on the bus does
 * so be quick, set flags for long running tasks to be called from the mainloop instead of running them directly,
 */
void receiveEvent(uint8_t howMany)
{
    if (howMany < 1)
    {
        // Sanity-check
        return;
    }
    if (howMany > TWI_RX_BUFFER_SIZE)
    {
        // Also insane number
        return;
    }

    reg_position = TinyWireS.receive();
    howMany--;
    if (!howMany)
    {
        // This write was only to set the buffer for next read
        return;
    }
    while(howMany--)
    {
        i2c_regs[reg_position%sizeof(i2c_regs)] = TinyWireS.receive();
        reg_position++;
    }
}


void setup()
{
    // TODO: Tri-state this and wait for input voltage to stabilize 
    pinMode(3, OUTPUT); // OC1B-, Arduino pin 3, ADC
    digitalWrite(3, LOW); // Note that this makes the led turn on, it's wire this way to allow for the voltage sensing above.

    pinMode(1, OUTPUT); // OC1A, also The only HW-PWM -pin supported by the tiny core analogWrite

    /**
     * Reminder: taking care of pull-ups is the masters job
     */

    TinyWireS.begin(I2C_SLAVE_ADDRESS);
    TinyWireS.onReceive(receiveEvent);
    TinyWireS.onRequest(requestEvent);

    
    // Whatever other setup routines ?
    
    digitalWrite(3, HIGH);
}

void loop()
{
    /**
     * This is the only way we can detect stop condition 
     * (http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=984716&sid=82e9dc7299a8243b86cf7969dd41b5b5#984716)
     * it needs to be called in a very tight loop in order not to miss any (REMINDER: Do *not* use delay() anywhere, use tws_delay() instead).
     * It will call the function registered via TinyWireS.onReceive(); if there is data in the buffer on stop.
     */
    TinyWireS_stop_check();
}

пример из библиотеки.

Значит это другая библиотека.
Но все равно что-то не сходится.

А у вас

uint16_t potVal;
...
TinyWireS.send(potVal);

Проверьте правильность подключения SDA, SCL и наличие подтягивающих резисторов.

NOTE! - It's very important to use pullups on the SDA & SCL lines!

Be sure to use pullups! (4.7K on 5V)

Немного поменял код

#include <TinyWireS.h>
#define SLAVE_ADDR 0x50
byte sendNumber = 0;

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

void loop()
{

}

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

  if (sendNumber == 100)
  {
    sendNumber = 0;
  }
}

В мастер скетче запрашиваю соответственно 1 байт, а не 2

#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(0x50, 1);

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


Не важно что я отправляю, приходит 255. Может в библиотеке дело?
Библиотеку от сюда брал - GitHub - rambo/TinyWire: My modifications to TinyWire Arduino libs

Оно в callback функцию (angleRequest) вообще не заходит...

uint16_t potVal;
...
TinyWireS.send(potVal);

правильно подмечено, а надо:

uint8_t potVal;
....
potVal = analogRead(3)>> 2;

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

ну как бы ясно было, что либо не считывает, либо не шлёт. первое проверил - работает. ну значит не шлёт. и тут или либа такая, или в скетче ошибка. никакого волшебства.