Problemi con Attiny85 e comunicazione I2C

Sto provando a programmare un attiny85 tramite il mio arduino UNO, facendogli acquisire dei dati da un sensore di prossimità APDS-9930.
La parte di programmazione l’ho conclusa con successo, ma sto avendo degli strani comportamenti per quanto riguarda l’hardware.

Lo schema di collegamento che sto utilizzando si può vedere nell’immagine sottostante.
L’attiny dovrebbe leggere i dati dal sensore e, quando un oggetto si trova in prossimità del sensore, dovrebbe accendere il led su PB4.

Con questa configurazione, Arduino viene usato per l’alimentazione a 3.3V e per il debugging. Ho cortocircuitato il pin di RESET con il GND e ho collegato al pin TX dell’arduino il corrispettivo pin TX usato nell’attiny. Ciò mi permette di leggere i messaggi inviati dall’attiny via seriale sul mio pc.

Il codice usato nel progetto è il seguente

#include <SoftwareSerial.h>
#include <Wire.h>
#include <APDS9930.h>

#define LED_PIN 4   // PB4 = pin fisico 3

// RX = -1 (non usato), TX = 3 (PB3, pin fisico 2)
SoftwareSerial mySerial(-1, 3);

APDS9930 apds = APDS9930();

void setup() {
  // LED
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);   // LED spento all'avvio

  mySerial.begin(9600);

  for (int i = 3; i > 0; i--) {
    mySerial.print(F("Inizio in... "));
    mySerial.println(i);
    delay(1000);
  }

  mySerial.println(F("\n--- DIAGNOSTICA APDS-9930 ---"));

  Wire.begin();
  // Wire.setClock(100000); // opzionale

  if (apds.init()) {
    mySerial.println(F("Inizializzazione: OK"));
  } else {
    mySerial.println(F("Inizializzazione: FALLITA"));
  }

  if (!apds.enableProximitySensor(false)) {
    mySerial.println(F("Errore abilitazione prossimita'"));
  }
}

void loop() {
  uint16_t proximity_data = 0;

  if (!apds.readProximity(proximity_data)) {
    mySerial.println(F("Errore lettura dati!"));
    digitalWrite(LED_PIN, LOW);   // sicurezza
  } else {
    mySerial.print(F("Valore: "));
    mySerial.println(proximity_data);

    if (proximity_data == 1023) {
      digitalWrite(LED_PIN, HIGH);
    } else {
      digitalWrite(LED_PIN, LOW);
    }
  }
}

L’unica cosa che mance nel setup è la scelta delle resistenze di pull-up R1 e R2.
In giro per il forum / su internet ho letto che vanno bene resistenze da 4.7K o 10K. Ho provato con tali valori, ma l’attiny continuava a stampare “Errore lettura dati”.

Ho cominciato a provare di tutto: aggiungere condensatori elettrolitici da pochi nF tra VCC e GND vicino al sensore o all’attiny, aumentare il valore delle resistenze, diminuire il valore delle resistenze, cambiare il codice, cambiare breadboard…

Ad un tratto qualcosa ha però fatto funzionare il tutto: collegando il pin A4 dell’arduino al pin PB2 dell’attiny, e il pin A5 dell’arduino al pin PB0 dell’attiny magicamente la comunicazione è partita. La configurazione “funzionante” diventa dunque la seguente

Non ho assolutamente compreso come mai questa configurazione “aiuti” l’attiny. Si consideri che nell’arduino sta girando il codice dello sketch di esempio “ArduinoISP” (giacché l’avevo appena usato per programmare l’attiny), ma comunque il pin RESET e GND sono cortocircuitati.

Facendo altri esperimenti, ho notato alcuni setup (sempre precari) che aiutavano l’attiny a comunicare correttamente con il sensore senza la necessità di collegare A4 e A5 di Arduino:

  • mettere un led al posto delle resistenze di pull-up
    Per qualche motivo tale led rende la comunicazione perfetta e non ci sono errori
  • mettere una resistenza di pull-up da 10K e toccare con le dita le sue due estremità
    In tal caso, solo ed esclusivamente se tocco le estremità della resistenza mentre è collegata si avvia la comunicazione correttamente
  • al posto di una singola resistenza di pull-up, metterne 3 in serie (10K + 10K + 47 = 20047)
    In tal caso la comunicazione funzionava per circa un minuto, poi crollava
  • al posto della resistenza di pull-up, mettere un resistore variabile 0→20k e provare a “giocherellare” con la manopola mettendolo circa ad un valore di 18K

Giusto per escludere ogni dubbio, ho provato anche a cambiare il clock dell’attiny (normalmente lo setto a 8MHz, ho provato a metterlo a 1MHz), ma non ha aiutato per nulla.
Ho provato a spostare qualche condensatore elettrolitico qua e là, ma nemmeno ciò è stato d’aiuto. Finora l’unica configurazione che rimane sempre stabile è quella che richiede A4 e A5 connessi all’attiny. Tutti gli altri metodi sono abbastanza “aleatori” e probabilmente il loro funzionamento dipende anche da altri fattori esterni che non sto considerando.

Giusto per fornire tutti i dettagli, noto che su A4 e A5 c’è una tensione di circa 0.10V. Inoltre il sensore funziona senza problemi se usato direttamente con Arduino. Faccio notare che potrebbe anche essere che il modulo in sé non è di ottima fattura, considerato che viene da Aliexpress. Comunque lascio una foto per completezza

Qualcuno più esperto di me saprebbe fornire qualche ipotesi su come mai si verifica questo comportamento ed eventualmente come affrontarlo ? E come mai il collegare i pin A4 e A5 aiuta così tanto ?

Io proverei ad alimentare diversamente il pin VL, potrebbe essere che la corrente disponibile dal regolatore 3.3. volt dell’UNO non sia sufficiente per i led. Prova a collegare il pin VL ai 5V con in serie un paio di diodi (1N4148 o 1N400X) e vedi se cambia qualcosa.

Ciao, Ale.

I am not Italian speaking man. To help you, I am taking the help of AI to get Italian <-------> English translation. If you know English, you can post your thread in English Section to receive plenty of interactions.

Non sono una persona che parla italiano. Per aiutarti, sto usando l’aiuto dell’AI per ottenere traduzioni tra italiano e inglese. Se conosci l’inglese, puoi pubblicare il tuo thread nella sezione in inglese per ricevere più interazioni.

1. This arrangement uses Arduino UNO as ISP Programmer for ATtiny85.

Questa configurazione utilizza Arduino UNO come programmatore ISP per l’ATtiny85.


Figure-1:

2. Make connection as per Fig-1:

Effettua i collegamenti come mostrato in Fig. 1.

3. Assuming fresh ATtiny85 and the Fuse Bytes are at factory settings to run MCU at 1 Mz and RESET/-pin is active.

Supponendo un ATtiny85 nuovo di zecca con i fuse byte impostati sui valori di fabbrica, il microcontrollore funziona a 1 MHz e il pin RESET è attivo.

4. Take out SDA and SCL lines from Proximity sensor.

Estrarre le linee SDA e SCL dal sensore di prossimità.

5. Upload ArduinoISP sketch from IDE examples into Arduino UNO using Upload command.

Carica lo sketch ArduinoISP dagli esempi dell’IDE sull’Arduino UNO utilizzando il comando Upload.

6. Upload the following sketch into ATtiny85 using "Arduino as ISP" Programmer and using "Upload Using Programmer" command.

Carica il seguente sketch sull’ATtiny85 utilizzando l’Arduino come programmatore ISP e il comando Upload Using Programmer.

Sketch (supplied by AI and not tested)

#include <TinyWireM.h>  // Software I2C for ATtiny
#define APDS_ADDR 0x39   // Default I2C address for APDS-9930
#define LED_PIN 4        // PB4 on ATtiny85

void setup() 
{
  TinyWireM.begin();      // Initialize software I2C
  pinMode(LED_PIN, OUTPUT);
  // Enable proximity sensor
  writeRegister(0x80, 0x03);  // ENABLE register: PON + PEN
}

void loop() 
{
  uint8_t proximity = readRegister(0x9C);  // PROXIMITY DATA register
  if (proximity > 50) 
{                    // Threshold for object detection
    digitalWrite(LED_PIN, HIGH);
    delay(200);
    digitalWrite(LED_PIN, LOW);
  }
  delay(50);  // Small delay to avoid flooding I2C
}

// Function to write 1 byte to APDS-9930 register
void writeRegister(uint8_t reg, uint8_t value) 
{
  TinyWireM.beginTransmission(APDS_ADDR);
  TinyWireM.send(reg);
  TinyWireM.send(value);
  TinyWireM.endTransmission();
}

// Function to read 1 byte from APDS-9930 register
uint8_t readRegister(uint8_t reg) {
  TinyWireM.beginTransmission(APDS_ADDR);
  TinyWireM.send(reg);
  TinyWireM.endTransmission();
  
  TinyWireM.requestFrom(APDS_ADDR, 1);
  if (TinyWireM.available()) 
{
    return TinyWireM.receive();
  }
  return 0;
}

7. After uploading --
remove left end of RESET/-pin wire of ATtiny85 from UNO and connect it with 5V.

remove connections of ATtiny85 from DPin-11 and DPin-12.

Connect SCL and SDA line of proximity sensor with ATtiny85's SCL and SDA.

Dopo il caricamento, rimuovi l’estremità sinistra del filo del pin RESET/- dell’ATtiny85 dall’Arduino UNO e collegala a 5V.

Rimuovi i collegamenti dell’ATtiny85 da DPin-11 e DPin-12.

Collega le linee SCL e SDA del sensore di prossimità agli SCL e SDA dell’ATtiny85.

8. Make a movement of an object near the sensor. Check tat LED1 makes flash.

Muovi un oggetto vicino al sensore. Verifica che il LED1 lampeggi.

Noto 3 cose:

  1. Arduino Uno R2 (cioè quello precedente l'R3?) con il Reset/ a massa non capisco come possa funzionare... E' costantemente resettato!

  2. L'ATtiny 85 ha il Reset/ scollegato?... In quelle condizioni può fare di tutto: funzionare o bloccarsi continuamente, secondo lo stato che assume il Reset/ in base a cariche che si accumulano o meno ogni momento.

  3. Non c'è nemmeno il minimo indispensabile 100nF ceramico vicinissimo all'alimentazione dell'ATtiny 85, senza il quale io non riuscivo nemmeno a programmarlo.

E’ voluto, l’UNO viene usato solo come alimentatore (sic!) a 3.3 V e per il convertitore seriale/USB, con cui leggere i messaggi del Tiny.

Ciao, Ale.

Ah! Ha bloccato l'Uno e ha usato la comunicazione seriale per l'ATtiny!
Restano il punto 2 e il punto 3.

Sì esatto! Il punto 2) è un’ottima osservazione, ho provato a sistemare collegando il pin RESET a VCC con in mezzo una resistenza da 10K ma non è cambiato nulla.

Il punto 3) invece è stato parecchio d’aiuto. Appena ho messo il condensatore ceramico il circuito ha iniziato a funzionare correttamente. In realtà avevo già provato a piazzare il condensatore qua e là, ma data la mia scarsa esperienza sono andato abbastanza alla cieca e non ho ottenuto risultati :roll_eyes:

Ora ho provato a lasciarlo attivo un po’ di tempo. Per un’oretta è andato senza problemi, poi ha cominciato a dare errore. Comunque è sicuramente meglio di prima che non andava proprio, magari ora provo a sistemare le resistenze di pull-up che attualmente sono impostate in serie a 20K ( la terza configurazione “di fortuna” che avevo provato).

Potrebbe anche essere la velocità troppo elevata? Magari abbassando a 1MHz si stabilizza (?)

Per il momento, grazie mille a tutti per il supporto ! Non mi aspettavo così tante risposte in poco tempo :laughing:

Quel modulo APDS ad occhio ha gia' pullup 10k onboard, quindi potresti provare anche senza.. Se non e' sufficiente, aggiungi altri 10k.