Sending LM35 reading from Master and recieving by slave/

so, hi everyone,
As you can see in the title , i have an issue regarding to send the reading value of LM35 temp sensor ,and recieving it by slave.
i know that variables like Float , int can't be sent over SPI bus.what i did was trying to convert the float value to a char Array.

so my question is : how i can send that char Array over SPI and how to recieve it by slave.

nb : if someone could help me to code the Master & slave for my project.( LM35 temp aquisition by master and sending over SPI for LCD display by slave ).

for now this is my attempts to code master & slave :slight_smile: ( i know that it is a broken code )

Master Program:

#include <SPI.h>
#include <stdlib.h>
#define PIN_LM35 A0
int adcVal;
char Value[12];
void setup(){
  
  Serial.begin(9600);
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV8); 
  digitalWrite(SS,HIGH);
}
void loop()
{
  adcVal = analogRead(PIN_LM35);
  float Vout=adcVal*5.0/1023*1000;
  delay(10);
  dtostrf(Vout,2,2,Value);
  char C;
  for(char*p=Value[0];C=*p;p++);{
  digitalWrite(SS,LOW);
  SPI.transfer(C);
  }
  Serial.print(C);
  digitalWrite (SS,HIGH);
  delay(100);
}

Slave Progam:

#include<SPI.h>
#include<Wire.h>
#include<LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
float Vout;
char buff[15];
volatile byte indx;
volatile boolean process;
void setup()
{
  lcd.init();// initialize the lcd
  lcd.clear();   
  lcd.backlight();  // open the backlight
  lcd.setCursor(0, 0);  // display position
  lcd.print("Tmp");
  lcd.setCursor(11,0);
  lcd.print(char(223));
  lcd.setCursor(12,0);
  lcd.print("C");
  lcd.setCursor(0, 1);
  lcd.print("Volt."); 
  lcd.setCursor(11,1);
  lcd.print("mV"); 
  Serial.begin(9600);
  pinMode(MISO,OUTPUT);                  
  SPCR |= _BV(SPE);
  indx=0;
  process=false;              
  SPI.attachInterrupt();
}
ISR (SPI_STC_vect)                        
{
  byte c=SPDR;
  if(indx<sizeof buff){
    buff[indx++]=c;        
  } process =true;                        
}
void loop(){

  if(process){
   process=false;
   Serial.println (buff); //print the array on serial monitor
   indx= 0; //reset button to zero
   Vout=atof(buff);
  float tempC = Vout / 10;
  float Voltage = Vout;
  lcd.setCursor(5, 0);  // display position
  lcd.print(tempC);
  // display position
  lcd.setCursor(6, 1);  
  lcd.print(Voltage);
  delay(10);         
 }
}

Many thanks
LOUKILI.

Welcome to the forum.

Did you learn programming by yourself ? Then it is a good start.
If you learned programming at school or took a course, then it is bad start.

Compare your code with: http://www.gammon.com.au/spi

Make the text of the code look good. Put every indent, every comma, every space, every new line at the right place. Use brackets in a consistent style.
If you do that, and also set the compiler warning to the maximum in the preferences, then you will immediately spot a number of bugs here:

  for( char *p=Value[0]; C=*p; p++)   // Value[0] is not a pointer
    ;                                 // I call this a "do nothing".

  {                                   // useless brackets are allowed in C++
    digitalWrite(SS,LOW);
    SPI.transfer(C);
  }                                   // a closing useless bracket

Try to make code that is as simple as possible. Do not try to be "smart". Add extra variables if needed, use multiple lines if that makes it better to read.

Don't try to transmit a zero-terminated string. Start by sending one byte, then try two bytes of an array, then try a number of bytes of a fixed length. Print them as hexadecimal numbers.
There is no need to convert it to readable text and convert it back to a integer. If you can send two bytes, then you can also send a integer of two bytes. If you can send four bytes, then you can also send a 'float'.

The "sizeof buff" is usually written as "sizeof(buff)": sizeof operator - cppreference.com

Why is there a "delay(10);" in the loop() of the Master ?

hello @koepel ,
Yeah you're! right i'm learning by my self ,so if you may share an exemple of sending a float via SPI, i would be gratfull.
thank you also for your notes about my writing.

Wouldn't is be easier to just transfer the A/D value,
and extract the temp at the receiving end.
Then all you need is this, assuming Uno (untested).
Leo..

#include <SPI.h>

void setup() {
  SPI.begin();
  analogReference(INTERNAL); // switch to 1.1volt Aref for higher stability and resolution
}

void loop() {
  SPI.transfer16(analogRead(A0)); // transfer 2-byte int
  delay(1000); // dirty delay
}
1 Like

@unoplo

The following two examples could be helpful for you:
Sketch-1: Exchanging float number between Master/Slave using SPI Port
Master Sketch:

#include<SPI.h>
byte myData[] = {0xAB, 0x12, 0x34, 0x56};

union myUData
{
  float x;
  byte myBytes[4];
};

myUData data;    //user defined data type myData is created using union keyword

void setup()
{
  Serial.begin(9600);
  SPI.begin();
  delay(100);
  SPI.setClockDivider(SPI_CLOCK_DIV16);//1 MBits/s
  //pinMode(SS, OUTPUT);
  digitalWrite(SS, LOW);  //Slave is selected
}

void loop()
{
  for (int i = 0; i < 4; i++)
  {
    myData[i] = SPI.transfer(myData[i]);
    delayMicroseconds(100); //allows Slave to process received byte
    Serial.println(myData[i], HEX);  //shows: 0xAB, 0x12, 0x34, 0x56
  }
  data.myBytes[3] = myData[0];
  data.myBytes[0] = myData[1];
  data.myBytes[1] = myData[2];
  data.myBytes[2] = myData[3];
  Serial.println(data.x, 2);//shows: 32.67
  Serial.println("======================");
  delay(1000);  //test interval
}

Slave Sketch:

#include<SPI.h>
int i = 0;
byte myData[] = {0x12, 0x34, 0x56, 0xAB};

union myUData
{
  float x;
  byte myBytes[4];
};
myUData data;
void setup()
{
  Serial.begin(9600);
  data.x = 32.67;
  SPI.setClockDivider(SPI_CLOCK_DIV16);//
  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()
{

}

ISR(SPI_STC_vect)
{
  SPDR = data.myBytes[i]; //places 0x12, then 0x34, then 0x56, then 0xAB
  i++;
  if (i == 4)     //4-byte data are sent
  {
    i = 0;          //array pointer is reset
  }
}

Sketch-2: Exchanging LM35's data between Master/Slave using SPI Port
spiLM35UnoNano
Master Sketch: Left blank and to be fulfilled by OP

#include<SPI.h>

void setup()
{

}

void loop()
{

}

Slave Sketch:

#include<SPI.h>
int i = 0;

union myUData
{
  float x;
  byte myBytes[4];
};

myUData data;

void setup()
{
  Serial.begin(9600);
  analogReference(INTERNAL);
   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()
{
  float myTemp = (float)100 * (1.1 / 1023.0) * analogRead(A3);
  data.x = myTemp;
  Serial.println(myTemp, 2);
  delay(2000);
}
ISR(SPI_STC_vect)
{
  SPDR = data.myBytes[i]; //places 0x12, then 0x34, then 0x56, then 0xAB
  i++;
  if (i == 4)     //4-byte data are sent
  {
    i = 0;          //array pointer is reset
  }
}

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