Issues using ATTiny85 as SPI slave with Arduino Uno as master

Hello,
I have written a sample code for Arduino Uno (SPI master) and ATTiny85 as SPI slave. For some reason its not working. Any clues what I am doing wrong?

To keep it simple, I am not even doing multiple slaves. Its just one master and one slave (hence no pin change interrupt needed, only Overflow interrupt on the slave side).

When I say "not working", it means, I have a debug LED on PB4 (pin 3) of ATTiny85. If the value sent by master is received successfully by slave, LED will light up. If not, LED will turn off. The LED never lights up. When I do logging via serial monitor on master side, I see that slave never receives the data sent from master. In my simple test logic, slave should only return specific values, 0x05 (called TEST_ACK) if it detects 0x02 received from master and 0x09 (called TEST_NACK) for anyother value received from master. Master only receives TEST_NACK for any value it sends, even if it is 0x02 (master should receive TEST_ACK for this value).

Some relevant info:

  • I am using another Arduino Uno as programmer for ATTiny85.
  • I have tested that ATTiny85 chip gets programmed fine via a blink led test.
  • The ISR USI_OVF_vect does get invoked everytime the master side does a SPI.Transfer(). Its just that USIBR/USIDR never receives the data sent by master.

When I am programming the ATTiny85 slave via Arduino Uno as programmer, I do following things:

Here is the master code (Arduino Uno as master):

#include <SPI.h>
#include "pins_arduino.h"

int dummyData = 7;
int slaveSelect = SS; // SS is pin 10
int slaveSelect1 = 9;
int delayTime = 500;
byte masterReceive;
//bool toggle = LOW;

// the setup function runs once when you press reset or power the board
void setup() {
  pinMode(slaveSelect, OUTPUT);
  pinMode(slaveSelect1, OUTPUT);
  digitalWrite(slaveSelect, HIGH);
  Serial.begin(9600); // set default baud rate for uart
  SPI.begin();
  // SPI.setBitOrder(MSBFIRST); // deprecated. use SPI.beginTranscation() with SPISettings
}

// the loop function runs over and over again forever
void loop() {
  {
    SPI.beginTransaction(SPISettings(9600, MSBFIRST, SPI_MODE0));
    digitalWrite(slaveSelect, LOW);
    delayMicroseconds(10);
    // send test string
    int sentData = 2;
    SPI.transfer(sentData);
    delay(500);
    byte recvData = SPI.transfer(dummyData);
    digitalWrite(slaveSelect, HIGH);
    SPI.endTransaction();
    Serial.print("Sent data:");
    Serial.print(sentData);
    Serial.print(":::Received data from slave:");
    Serial.println(recvData);
  }

Here is the slave code (ATTiny85 as slave):

#define CS PB3    // Chip Select or Slave Select
#define DO PB1    // MISO or Data Out
#define DI PB0    // MOSI or Data In
#define SCK PB2   // Clock
#define LED PB4   // Test LED
#define TEST_DATA 0x02
#define TEST_ACK 0x05
#define TEST_NACK 0x09
void setup() {

  cli(); // Deactivate interrupts
  SPI_USI_init();
  sei(); // Activate interrupts
}

void loop() {
  // put your main code here, to run repeatedly:

}


void SPI_USI_init() {
  DDRB &= ~(1 << DI);                 // Set DI as input
  DDRB &= ~(1 << SCK);                // Set SCK as input
  DDRB |= 1 << LED;                   // Set LED pin as output
  DDRB |= 1 << DO;                    // MISO Pin has to be an output

  USICR = ((1 << USIWM0)
           | (1 << USICS1) 
           | (1 << USIOIE)); // Activate 3- Wire Mode and use of external clock and enable overflow interrupt

  PORTB &= ~(1 << LED);               // Turn LED off
  delay(500);                         // Let things settle
}


// USI interrupt routine. Always executed when 4-bit overflows (after 16 clock edges = 8 clock cycles):

// for test purposes: the master will send TEST_DATA as data and should receive from slave TEST_ACK as response
// for test purposes: if the master sends anything other than TEST_DATA, it will receive from slave TEST_NACK as response

ISR (USI_OVF_vect) {
  byte received = USIBR;

  if (received == TEST_DATA) {
    USIDR = TEST_ACK; //ACK for successfully receiving TEST_DATA
    //Testing: operation to turn PB4 (LED) on. (Not needed for USI)
    PORTB |= (1 << LED);
  }
  else {
    USIDR = TEST_NACK; //NACK indicating non TEST_DATA value received
    //Testing: operation to turn PB4 (LED) off. (Not needed for USI)
    PORTB &= ~(1 << LED);
  }
  
  USISR = 1 << USIOIF;
}

Any help will be appreciated.
Best Regards,
aquaman

Upload the following sketch in your UNO and check if your Serial Monitor shows 5 that is coming from ATTiny85. If not, there is something wrong with the Slave Sketch.

#include <SPI.h>
volatile bool flag = false;
volatile byte y;

void setup ()
{
  Serial.begin(9600);
  SPI.begin();  //LH --> SPE-bit, LH--> I-bit
  digitalWrite(SS, LOW);   //Slave is selceted
  SPI.attachInterrupt(); //LH--->SPIE-bit
}

void loop()
{
  SPI.transfer(0x02); //SPDR = 0x02
  if(flag == true)
  {
    Serial.println(y, HEX);
    flag = false;
  }
  delay(1000);
}

ISR(SPI_STC_vect)
{
  flag = true;
  y = SPDR;
}
1 Like

There was a discussion on AVRFreaks that I located via a google search that seems to be very similar to what you are trying - 328P master and TINY85 as a slave on SPI:
https://www.avrfreaks.net/forum/attiny85-respond-slave-usi-spi-mode
Might be worth a read as the OP says that they got it working.

1 Like

Hello @GolamMostafa ,
Thanks for your reply.

I uploaded the sketch to Arduino Uno that is acting as master. Heck, I even added

pinMode(SS, OUTPUT);

before the

digitalWrite(SS, LOW);

Here is what I see from the serial monitor:

21:37:30.710 -> 0
21:37:31.706 -> 0
21:37:32.701 -> 0
21:37:33.697 -> 0
21:37:34.693 -> 0
21:37:35.688 -> 0
21:37:36.717 -> 0
21:37:37.712 -> FF
21:37:38.708 -> 0
21:37:39.703 -> 0
21:37:40.699 -> 0
21:37:41.727 -> 0
21:37:42.723 -> FF
21:37:43.718 -> 0
21:37:44.714 -> 0
21:37:45.709 -> 0
21:37:46.705 -> 0
21:37:47.733 -> 0
21:37:48.729 -> 0
21:37:49.724 -> 0
21:37:50.719 -> FE
21:37:51.715 -> 0
21:37:52.710 -> 1
21:37:53.739 -> FC
21:37:54.734 -> 0
21:37:55.729 -> 0
21:37:56.725 -> 0
21:37:57.720 -> 0
21:37:58.749 -> 0
21:37:59.744 -> 0
21:38:00.739 -> FC
21:38:01.735 -> 0
21:38:02.730 -> 0
21:38:03.725 -> 0
21:38:04.754 -> 3
21:38:05.749 -> FF
21:38:06.745 -> 0
21:38:07.740 -> 0
21:38:08.736 -> 0
21:38:09.764 -> 3
21:38:10.759 -> FC
21:38:11.755 -> 0
21:38:12.750 -> 0
21:38:13.745 -> FC
21:38:14.741 -> 0
21:38:15.769 -> 0
21:38:16.764 -> 0
21:38:17.760 -> 0
21:38:18.755 -> 0
21:38:19.751 -> 0
21:38:20.746 -> 3
21:38:21.775 -> FC
21:38:22.770 -> 0
21:38:23.765 -> 0
21:38:24.761 -> 0
21:38:25.756 -> FF
21:38:26.752 -> 0
21:38:27.780 -> 0
21:38:28.776 -> 0
21:38:29.771 -> 0
21:38:30.767 -> 0
21:38:31.762 -> 0
21:38:32.758 -> 7
21:38:33.786 -> FC
21:38:34.782 -> 0
21:38:35.778 -> 7
21:38:36.774 -> FF
21:38:37.770 -> FC
21:38:38.798 -> 0
21:38:39.794 -> 0
21:38:40.789 -> 0
21:38:41.784 -> 0
21:38:42.780 -> 0
21:38:43.775 -> F8
21:38:44.808 -> 0
21:38:45.798 -> 0
21:38:46.793 -> 3
21:38:47.788 -> FE

Its getting garbage values from slave.

Am still wondering what is incorrect on slave side. Its not even multiple slave scenario, where I would have suspected bus contention issues. Its just one master and one slave.

Regards,
aquaman

Hello @markd833 ,
Thank you for your reply. I did go through that link previously, while doing my research. In fact, its from there that I got my starting code.
But thanks for mentioning it again.. I will re-read it to check if I missed something. I am sure, I am doing something so silly that I will have a face-palm moment when I do figure it out.

Regards,
aquaman

Some more relevant info, in case it might help in finding what is going wrong.

When I am programming the ATTiny85 slave via Arduino Uno as programmer, I do following things:

  1. I am using this ATTiny HAL https://github.com/SpenceKonde/ATTinyCore
  2. Clock source (only set on bootload):"8 Mhz internal"

I am not sure if 8Mhz internal clock will have any difference for ATTiny85 slave as ATTiny85 is being used as SPI slave where its the external clock coming from master to the slave that is driving the internal overflow counters (I think so... haven't read on datasheet that closely at this point)

Am still digging to see what is the issue on the slave side that is causing it to receive and send garbage values.

Have you tried to use the ATtiny85 at 16MHz, the PLL option. It is one of the nice features of the 85 - to be clocked at 16MHz internal.

1 Like

Hello @Willem43 ,
Thank you for your reply. I tried the clock source 16MHz PLL option on ATTiny85 slave. Still no dice. Master is still getting garbage values from slave when I use the master code as suggested by @GolamMostafa. When I use the SPI master code as in my first post, master receives only 0x09 from the slave no matter what it sends to slave. Not sure why the difference.

Best Regards,
aquaman

1. Sketch of post #2 is tested using another UNO.
2. When you include SPI.h, the SS (DPin-10) is automatically output and HIGH.
3. The default SPI speed is 4 MHz (as dicttaed by Master) and does not depend on the operating speed of Slave; but, the Slave must run at higher speed of 4 MHz.

3. I am giving you below tested SPI-Master Sketch and SPI-Slave sketch; where, Master sends 0x02 to Slave at 1-sec interval and the Slave sends 0x05 in return and the values are shown on their respective Serial Monitors. You can follow the logic of these sketches and accordingly design the sketch for your ATtiny85. If possible, convert my Slave Sketch into ATtiny85's sketch and post it which I will check (theoretically) for validity.

SPI-Master Sketch (UNO)

#include <SPI.h>
volatile bool flag = false;
volatile byte y;

void setup ()
{
  Serial.begin(9600);
  SPI.begin();  //LH --> SPE-bit, LH--> I-bit
  digitalWrite(SS, LOW);   //Slave is selceted
  SPI.attachInterrupt(); //LH--->SPIE-bit
}

void loop()
{
  SPI.transfer(0x02); //SPDR = 0x02
  if(flag == true)
  {
    Serial.println(y, HEX);
    flag = false;
  }
  delay(1000);
}

ISR(SPI_STC_vect)
{
  flag = true;
  y = SPDR;
}

SPI-Slave Sketch (NANO)

#include<SPI.h>

volatile bool flag = false;
volatile byte y;
byte z = 0x05;

void setup()
{
  Serial.begin(9600);
  pinMode(SS, INPUT_PULLUP);  // ensure SS stays high for now
  pinMode(MISO, OUTPUT);
  SPCR |= _BV(SPE);
  SPCR |= !(_BV(MSTR)); //Arduino is Slave
  SPI.attachInterrupt();   //interrupt logic is enabled
}

void loop()
{
  if (flag == true)
  {
    Serial.println(y, HEX);  //shows: 0x3456
    flag = false;
  }
}

ISR(SPI_STC_vect)
{
  y = SPDR;
  SPDR = z;
  flag = true;
}

Master Screen

5
5
5

Slave Screen

2
2
2

4. In the meantime, I can try UNO-ATtiny85 using SPI Port if you can provide me a step-by-step tutorial on the setup of ATtiny85 on the breadboard and loading program codes into its flash using an UNO as an ISP Programmer.

1 Like

Hello @GolamMostafa ,
My most sincere thanks to you for your offer to run the code. Your inputs did help me steer towards resolution.

Thanks,
aquaman

1 Like

Glad to know that the sketches of post #9 would be helpful for you.

I figured out the issue. Its the USIBR in the slave ISR that is causing the problem. Let me put it more clearly:

Does not work

ISR (USI_OVF_vect) {
  byte received = USIBR;

  if (received == TEST_DATA) {
    USIDR = TEST_ACK; //ACK for successfully receiving TEST_DATA
    //Testing: operation to turn PB4 (LED) on. (Not needed for USI)
    PORTB |= (1 << LED);
  }
  else if (received == 0x06) {
    USIDR = 0x07; //ACK for successfully receiving TEST_DATA
    //Testing: operation to turn PB4 (LED) on. (Not needed for USI)
    PORTB |= (1 << LED);
  }
  else {
    USIDR = TEST_NACK; //NACK indicating non TEST_DATA value received
    //Testing: operation to turn PB4 (LED) off. (Not needed for USI)
    PORTB &= ~(1 << LED);
  }
  
  USISR = 1 << USIOIF;
}

This works

ISR (USI_OVF_vect) {
  byte received = USIDR;

  if (received == TEST_DATA) {
    USIDR = TEST_ACK; //ACK for successfully receiving TEST_DATA
    //Testing: operation to turn PB4 (LED) on. (Not needed for USI)
    PORTB |= (1 << LED);
  }
  else if (received == 0x06) {
    USIDR = 0x07; //ACK for successfully receiving TEST_DATA
    //Testing: operation to turn PB4 (LED) on. (Not needed for USI)
    PORTB |= (1 << LED);
  }
  else {
    USIDR = TEST_NACK; //NACK indicating non TEST_DATA value received
    //Testing: operation to turn PB4 (LED) off. (Not needed for USI)
    PORTB &= ~(1 << LED);
  }
  
  USISR = 1 << USIOIF;
}

My master code is the same as in post #1.

The only change that I did was in slave ISR was to read the data sent from master from USIDR instead of USIBR. If I do this, slave is able to receive correct values form master. If I use USIBR, it does not work (meaning slave is getting garbage from master).

I am not sure why this is. USIBR is meant to shadow USIDR for data received from master. Per the datasheet (here), on page 115 it says its ok to read received data from USIBR rather than USIDR.

Just in case someone stumbles across the same issue, here is what worked for me.
SPI Master (Arduino Uno):


#include <SPI.h>
#include "pins_arduino.h"

int dummyData = 7;
int slaveSelect = SS; // SS is pin 10
int slaveSelect1 = 9;
int delayTime = 500;
byte masterReceive;
//bool toggle = LOW;

// the setup function runs once when you press reset or power the board
void setup() {
  pinMode(slaveSelect, OUTPUT);
  pinMode(slaveSelect1, OUTPUT);
  digitalWrite(slaveSelect, HIGH);
  Serial.begin(9600); // set default baud rate for uart
  SPI.begin();
  // SPI.setBitOrder(MSBFIRST); // deprecated. use SPI.beginTranscation() with SPISettings
}

// the loop function runs over and over again forever
void loop() {
  {
    SPI.beginTransaction(SPISettings(9600, MSBFIRST, SPI_MODE0));
    digitalWrite(slaveSelect, LOW);
    delayMicroseconds(10);
    // send test string
    int sentData = 2;
    SPI.transfer(sentData);
    delay(500);
    byte recvData = SPI.transfer(dummyData);
    digitalWrite(slaveSelect, HIGH);
    SPI.endTransaction();
    Serial.print("Sent data:");
    Serial.print(sentData);
    Serial.print(":::Received data from slave:");
    Serial.println(recvData);
  }
  {
    SPI.beginTransaction(SPISettings(9600, MSBFIRST, SPI_MODE0));
    digitalWrite(slaveSelect, LOW);
    delayMicroseconds(10);
    // send test string
    int sentData = 3;
    SPI.transfer(sentData);
    delay(500);
    byte recvData = SPI.transfer(dummyData);
    digitalWrite(slaveSelect, HIGH);
    SPI.endTransaction();
    Serial.print("Sent data:");
    Serial.print(sentData);
    Serial.print(":::Received data from slave:");
    Serial.println(recvData);
  }
  {
    SPI.beginTransaction(SPISettings(9600, MSBFIRST, SPI_MODE0));
    digitalWrite(slaveSelect, LOW);
    delayMicroseconds(10);
    // send test string
    int sentData = 6;
    SPI.transfer(sentData);
    delay(500);
    byte recvData = SPI.transfer(dummyData);
    digitalWrite(slaveSelect, HIGH);
    SPI.endTransaction();
    Serial.print("Sent data:");
    Serial.print(sentData);
    Serial.print(":::Received data from slave:");
    Serial.println(recvData);
  }
  {
    SPI.beginTransaction(SPISettings(9600, MSBFIRST, SPI_MODE0));
    digitalWrite(slaveSelect, LOW);
    delayMicroseconds(10);
    // send test string
    int sentData = 2;
    SPI.transfer(sentData);
    delay(500);
    byte recvData = SPI.transfer(dummyData);
    digitalWrite(slaveSelect, HIGH);
    SPI.endTransaction();
    Serial.print("Sent data:");
    Serial.print(sentData);
    Serial.print(":::Received data from slave:");
    Serial.println(recvData);
  }
}

SPI Slave (ATTiny85)

#define CS PB3    // Chip Select or Slave Select
#define DO PB1    // MISO or Data Out
#define DI PB0    // MOSI or Data In
#define SCK PB2   // Clock
#define LED PB4   // Test LED
#define TEST_DATA 0x02
#define TEST_ACK 0x05
#define TEST_NACK 0x09
void setup() {

  cli(); // Deactivate interrupts
  SPI_USI_init();
  sei(); // Activate interrupts
}

void loop() {
  // put your main code here, to run repeatedly:

}


void SPI_USI_init() {
  DDRB &= ~(1 << DI);                 // Set DI as input
  DDRB &= ~(1 << SCK);                // Set SCK as input
  DDRB |= 1 << LED;                   // Set LED pin as output
  DDRB |= 1 << DO;                    // MISO Pin has to be an output

  USICR = ((1 << USIWM0)
           | (1 << USICS1) 
           | (1 << USIOIE)); // Activate 3- Wire Mode and use of external clock and enable overflow interrupt

  PORTB &= ~(1 << LED);               // Turn LED off
  delay(500);                         // Let things settle
}


// USI interrupt routine. Always executed when 4-bit overflows (after 16 clock edges = 8 clock cycles):

// for test purposes: the master will send TEST_DATA as data and should receive from slave TEST_ACK as response
// for test purposes: if the master sends anything other than TEST_DATA, it will receive from slave TEST_NACK as response

ISR (USI_OVF_vect) {
  byte received = USIDR;

  if (received == TEST_DATA) {
    USIDR = TEST_ACK; //ACK for successfully receiving TEST_DATA
    //Testing: operation to turn PB4 (LED) on. (Not needed for USI)
    PORTB |= (1 << LED);
  }
  else if (received == 0x06) {
    USIDR = 0x07; //ACK for successfully receiving TEST_DATA
    //Testing: operation to turn PB4 (LED) on. (Not needed for USI)
    PORTB |= (1 << LED);
  }
  else {
    USIDR = TEST_NACK; //NACK indicating non TEST_DATA value received
    //Testing: operation to turn PB4 (LED) off. (Not needed for USI)
    PORTB &= ~(1 << LED);
  }
  
  USISR = 1 << USIOIF;
}

The above scenario is tested for master and single slave.

1 Like

I would be glad to know if my Master sketch of post #9 does communicate with your ATtiny85?

I would recommend to shorten your ISR and let the loop() function carry out the tasks.

Hello @GolamMostafa,

When I ran master sketch from post #9, with the slave sketch from post #13, I get this output which is not the expected output:

11:20:48.060 -> 0
11:20:49.055 -> 0
11:20:50.049 -> 0
11:20:51.044 -> 0
11:20:52.072 -> 7
11:20:53.066 -> FF
11:20:54.061 -> FF
11:20:55.056 -> 0
11:20:56.054 -> 0

Possibly this is because SPI_STC_vect is a slave SPI interrupt (never saw it used in a master.. though my experience on arduino is tops 3 weeks... so please don't take my word for it). However, I remember seeing your post regarding this (here).

Very good point. Indeed, business logic should be in loop or separate non-blocking thread instead of ISR.
Here is the updated slave code:

#define CS PB3    // Chip Select or Slave Select
#define DO PB1    // MISO or Data Out
#define DI PB0    // MOSI or Data In
#define SCK PB2   // Clock
#define LED PB4   // Test LED
#define TEST_DATA 0x02
#define TEST_ACK 0x05
#define TEST_NACK 0x09

volatile bool received_flag;
volatile byte received;
void setup() {

  cli(); // Deactivate interrupts
  SPI_USI_init();
  sei(); // Activate interrupts
  received_flag = false;
  received = 0x0;
}

void loop() {
  // put your main code here, to run repeatedly:
  if (received_flag == true) {
    received_flag = false;
    if (received == TEST_DATA) {
      USIDR = TEST_ACK; //ACK for successfully receiving TEST_DATA
      //Testing: operation to turn PB4 (LED) on. (Not needed for USI)
      PORTB |= (1 << LED);
    }
    else if (received == 0x06) {
      USIDR = 0x07; //ACK for successfully receiving 0x06
      //Testing: operation to turn PB4 (LED) on. (Not needed for USI)
      PORTB |= (1 << LED);
    }
    else {
      USIDR = TEST_NACK; //NACK indicating non TEST_DATA value received
      //Testing: operation to turn PB4 (LED) off. (Not needed for USI)
      PORTB &= ~(1 << LED);
    }
  }
}


void SPI_USI_init() {
  DDRB &= ~(1 << DI);                 // Set DI as input
  DDRB &= ~(1 << SCK);                // Set SCK as input
  DDRB |= 1 << LED;                   // Set LED pin as output
  DDRB |= 1 << DO;                    // MISO Pin has to be an output

  USICR = ((1 << USIWM0)
           | (1 << USICS1)
           | (1 << USIOIE)); // Activate 3- Wire Mode and use of external clock and enable overflow interrupt

  PORTB &= ~(1 << LED);               // Turn LED off
  delay(500);                         // Let things settle
}


// USI interrupt routine. Always executed when 4-bit overflows (after 16 clock edges = 8 clock cycles):

// for test purposes: the master will send TEST_DATA as data and should receive from slave TEST_ACK as response
// for test purposes: if the master sends anything other than TEST_DATA, it will receive from slave TEST_NACK as response

ISR (USI_OVF_vect) {
  received = USIDR;
  received_flag = true;
  USISR = 1 << USIOIF;
}

Best Regards,
aquaman

1 Like

When I run the same sketch with NANO-slave, the communication is fine.

As you have said that your sketch communicates well with ATtint85. Now, can you please post the screen output of your Master sketch to see that the Master has really received 5 from ATtiny85 in response to sending 0x02?

Hello @GolamMostafa,

Attached is the master's serial monitor output from using the master code in post #13 and slave code code in post #15.

12:02:24.605 -> Sent data:3:::Received data from slave:9
12:02:25.135 -> Sent data:6:::Received data from slave:7
12:02:25.633 -> Sent data:2:::Received data from slave:5
12:02:26.130 -> Sent data:2:::Received data from slave:5
12:02:26.628 -> Sent data:3:::Received data from slave:9
12:02:27.125 -> Sent data:6:::Received data from slave:7
12:02:27.622 -> Sent data:2:::Received data from slave:5
12:02:28.120 -> Sent data:2:::Received data from slave:5
12:02:28.617 -> Sent data:3:::Received data from slave:9
12:02:29.148 -> Sent data:6:::Received data from slave:7
12:02:29.645 -> Sent data:2:::Received data from slave:5
12:02:30.143 -> Sent data:2:::Received data from slave:5
12:02:30.640 -> Sent data:3:::Received data from slave:9
12:02:31.138 -> Sent data:6:::Received data from slave:7
12:02:31.635 -> Sent data:2:::Received data from slave:5
12:02:32.133 -> Sent data:2:::Received data from slave:5
12:02:32.630 -> Sent data:3:::Received data from slave:9
12:02:33.127 -> Sent data:6:::Received data from slave:7
12:02:33.658 -> Sent data:2:::Received data from slave:5
12:02:34.155 -> Sent data:2:::Received data from slave:5
12:02:34.653 -> Sent data:3:::Received data from slave:9
12:02:35.150 -> Sent data:6:::Received data from slave:7
12:02:35.647 -> Sent data:2:::Received data from slave:5
12:02:36.145 -> Sent data:2:::Received data from slave:5
12:02:36.642 -> Sent data:3:::Received data from slave:9
12:02:37.140 -> Sent data:6:::Received data from slave:7
12:02:37.637 -> Sent data:2:::Received data from slave:5
12:02:38.167 -> Sent data:2:::Received data from slave:5
12:02:38.665 -> Sent data:3:::Received data from slave:9
12:02:39.162 -> Sent data:6:::Received data from slave:7
12:02:39.659 -> Sent data:2:::Received data from slave:5
12:02:40.157 -> Sent data:2:::Received data from slave:5
12:02:40.654 -> Sent data:3:::Received data from slave:9
12:02:41.152 -> Sent data:6:::Received data from slave:7
12:02:41.649 -> Sent data:2:::Received data from slave:5
12:02:42.147 -> Sent data:2:::Received data from slave:5
12:02:42.677 -> Sent data:3:::Received data from slave:9

This is indeed expected output from slave. The slave should:

  1. Send 0x5 when receiving 0x2 from master
  2. Send 0x7 when receiving 0x6 from master
  3. Send 0x9 when receiving anything other than 0x2 or 0x6 from master

These are contrived values. In reality, sensor information will be sent here.

Best Regards,
aquaman

Please, check if the following sketch (a very short versio of yours') communicates with ATtiny85. If it works, then I will think to replace the ISR() rotine of my Master Program of post #9.

#include <SPI.h>

void setup()
{
  Serial.begin(9600); // set default baud rate for uart
  SPI.begin();
  digitalWrite(SS, LOW);
}

void loop()
{
  SPI.transfer(0x02);
  delayMicroseconds(100);
  byte recvData = SPI.transfer(0x07);
  Serial.println(recvData);
  delay(1000);
}

Hello @GolamMostafa ,

Here is the master's serial monitor output. Does not look like expected output:

12:59:23.305 -> 0
12:59:24.300 -> 0
12:59:25.328 -> 248
12:59:26.323 -> 0
12:59:27.351 -> 255
12:59:28.346 -> 0
12:59:29.374 -> 0
12:59:30.368 -> 0
12:59:31.397 -> 0
12:59:32.391 -> 255
12:59:33.386 -> 255
12:59:34.414 -> 0
12:59:35.442 -> 3
12:59:36.436 -> 0
12:59:37.465 -> 0
12:59:38.459 -> 255
12:59:39.487 -> 0
12:59:40.482 -> 255
12:59:41.510 -> 0
12:59:42.505 -> 0
12:59:43.533 -> 0
12:59:44.528 -> 0
12:59:45.556 -> 0
12:59:46.550 -> 0
12:59:47.578 -> 0
12:59:48.573 -> 0
12:59:49.601 -> 0
12:59:50.596 -> 0
12:59:51.591 -> 1
12:59:52.619 -> 255
12:59:53.614 -> 0

However, when I encapsulate your code inside a transaction pattern, its works fine. I think the issue is incorrect SPI mode and endian settings.

Here is the same code, just encapsulated inside a transaction:

#include <SPI.h>

void setup()
{
  Serial.begin(9600); // set default baud rate for uart
  SPI.begin();
}

void loop()
{
  SPI.beginTransaction(SPISettings(9600, MSBFIRST, SPI_MODE0));
  digitalWrite(SS, LOW);
  delayMicroseconds(10);
  SPI.transfer(0x02);
  delay(10);
  byte recvData = SPI.transfer(0x07);
  Serial.println(recvData);
  delay(1000);
  digitalWrite(SS, HIGH);
  SPI.endTransaction();
}

This code gives this output on master's serial monitor:>

13:06:48.274 -> 5
13:06:49.269 -> 5
13:06:50.297 -> 5
13:06:51.292 -> 5
13:06:52.321 -> 5
13:06:53.316 -> 5
13:06:54.344 -> 5
13:06:55.339 -> 5
13:06:56.367 -> 5
13:06:57.362 -> 5
13:06:58.390 -> 5
13:06:59.384 -> 5
13:07:00.412 -> 5
13:07:01.408 -> 5

Which is indeed expected output.

Best regards,
aquaman

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.