SPI without Pin 10

first post, so please bear with me.

I looked and looked but cannot find an example of anyone using the SPI library on a (software?) alternative to Pin 10.

I have my radio on 10 and am looking to add a shift register. I need access to the clock.

Any suggestions?

SPI supports multiple devices in parallel, each needs its own CS output. Pin 10 Must be an output for the uC to be the SPI master. So you can have:

digitalWrite (pin10, LOW);
SPI.transfer(data1);
digitalWrite (pin10, HIGH);

digitalWrite (pin8, LOW);
SPI.transfer(data2);
digitalWrite (pin8, HIGH);

to transfer data out to 2 different devices, with SCK and MOSI going to both in parallel, and pin8 and pin10 being the control of whether device does something with the data or not.

thanks for the quick response. So I need a little more help. right now I have my radio on:

10 CS 11 MOSI 12 MISO 12 SCK

are you saying that I can a) also connect 10 to my shift register (clock) b) connect the Latch Pin to 8 and the c) Data pin to any open pin,

then toggle to pin 8 (data2) push out the values and toggle back to (data1)

Sorry, but as you can tell, I am not keen on these things overlapping. My radio configuration is inflexible that is why I'm asking.

Are you planning on using shiftOut? You don't need D10 for that. http://arduino.cc/en/Reference/ShiftOut

SurferTim:
Are you planning on using shiftOut? You don’t need D10 for that.
http://arduino.cc/en/Reference/ShiftOut

That looks straightforward, thanks.

I would like to learn the hardware method, but this does solve my problem.

Appreciate the help.

What I am saying is connect D13 to the shift register SRCLK pin D11 (MOSI) to the Serial Data In pin Connect D8 to the RCLK (latch) pin

D10 is then used as CS/latch to the radio, and D8 is the latch for the shift register (although if it is 74HC595 type, it is really the output register clock) SRCLR connects to +5, OE/ connects to GND, or to a control pin if you need to use it as output enable. Connect a 0.1uF cap from shift register's VCC pin to Gnd.

Then only 1 more pin is used, and not 3 more to use shiftOut( )

Understood now, great.

I am desperate to conserve pins in this project so this helps a lot. Plus, I gather the hardware solution will be faster pushing out the bits (assuming little in the way of radio traffic).

Now I have two new ways to try!

I really appreciate the assistance. Thanks.

I grew up in Mass, so its nice to get help from my peeps XD

And where are you now? Despite having lived here for most of my adult life, I still do not consider myself a Massachusettian, and I still cheer for the Giants first when they play the Patriots. New Yorker thru & thru!

Ha! right now I'm in Giants territory here in New Jersey. Still a RedSox, Pats fan...

SurferTim:
Are you planning on using shiftOut? You don’t need D10 for that.
http://arduino.cc/en/Reference/ShiftOut

I was able to get this all going very well with your assistance. I have attached where I am for the moment, but I have another question.

This sketch is for a weather station and this will be a slave Nano controlling the output to the weather and message portion of the project. While I was able (with the assistance of those present) to move a short message via serial from the master to the slave, I need help getting ‘chunks’ of data.

I would like to get the Weather, OutsideTemp, InsideTemp,Units, and MessageFlag in a format with which I can decode it and make it work for my sketch. Something like:

$A,-3,72,F,1#

$ = start of transmit
A = char
-3 = int
72 = int
F = boolean
1 = boolean

= end of transmit

I’m using this for the weather, but I can only retrieve a single char, experimenting with variable types has gotten me nowhere.

void loop()
{
  //
  //GO get Temp and Weather
  //
   if (Serial.read() == '

ClockSlaveWeatherSkitsFinal.ino (14 KB))
  {
    for (int i=0;i<3; i++)
    {
      delay(1);
      MessageLength = i;
      Message[i] = Serial.read();
      delay(10);
      Serial.print(“read a: “);Serial.println(Message[i]);
      if(Message[i] ==’#’);
      {
        break;
      }
    }
    delay(10);
    Serial.print(“the message was:”);
    for(int i=0;i<MessageLength;i++)
    delay(10);
    {
      Serial.print(Message[MessageLength]);
      delay(10);
    }
    Serial.println(”/”);
  }
    switch (Message[MessageLength])
    {
      case 65://an “A” was sent
        Serial.println(“Sunny”);


....

[ClockSlaveWeatherSkitsFinal.ino|attachment](upload://nqjZgq7gepNYisVkhgXVeDcUQTv.ino) (14 KB)
if (Serial.available() >8){ // enough data arrived?
if (Serial.read() == '

){ // correct start byte? // now read all the rest . . } // end start byte test } // end data available check ```

can't believe after the shift register and 3D array I'm struggling with this part.

This doesn't work:

char masterMessage[18];///
int msgLength = 0;
boolean IsMessage=false;
void setup()
{
  Serial.begin(19200);
}

void loop()
{
  if (Serial.available() >8){ // enough data arrived?
    if (Serial.read() == '

Can you see what I'm doing wrong? I should have gone to a better school){ // correct start byte?       while (Serial.read() != '#')       {         masterMessage[msgLength] = Serial.read();         msgLength=msgLength++;       }           } // end start byte test     IsMessage=true;   } // end data available check if (IsMessage){   for (int i=0;i=msgLength;i=i++){     Serial.println(masterMessage[i]);   }   Serial.println(" ");   IsMessage = false;   }   msgLength = 0; } ```

Can you see what I'm doing wrong? I should have gone to a better school

This is gonna read half the data on you while (Serial.read() != '#') so this part will only see like every other byte masterMessage[msgLength] = Serial.read();

Instead, try something like while (done !=true){ do the 2nd part, masterMessage[msgLength] = Serial.read();

and then test if (masterMessage[msgLength] == "#"){done = true;} else {msgLength=msgLength++;}

Something like that.

So this works:

char masterMessage[20];///
int msgLength = 0;
boolean IsMessage=false;
boolean done;
void setup()
{
  Serial.begin(19200);
}

void loop()
{
  if (Serial.available() >8){ // enough data arrived?
  done=false;
    if (Serial.read() == '

Output attached for this string
$A,-3,72,F,1#
entered into the serial terminal.

Can you tell me why it seems a bit fussy, and I had to add the delay to make it work?

It was printing back some odd characters…

){ // correct start byte?
     while  (done != true) {
       masterMessage[msgLength] = Serial.read();
       delay(10);
       if (masterMessage[msgLength] == ‘#’){done=true;}
       msgLength=msgLength++;
     }
   }
   IsMessage=true;
 } // end data available check
if (IsMessage){
 for (int i=0;i<msgLength;i=i++){
   Serial.println(masterMessage[i],DEC);
 }
 Serial.println(" ");
 IsMessage = false;
 }
 msgLength = 0;
}


Output attached for this string 
$A,-3,72,F,1#
entered into the serial terminal.

Can you tell me why it seems a bit fussy, and I had to add the delay to make it work?

It was printing back some odd characters...

![Screen Shot 2014-05-16 at 12.02.52 PM.png|1140x508](upload://fVrl3wTM8ViKLDY7j0U8E9OUbOW.png)

![WithoutDelays.png|1064x932](upload://iwY6WVRG7RoSoiCmlJEUMeqBJQU.png)

Make this qty larger if (Serial.available() >8){ // enough data arrived? My count of the data being sent was not large enough, try >=13 vs >8 Otherwise can get a lot of empty incoming buffer reads.

Data seems to agree with this chart: www.asciitable.com

@CrossRoads

I abandoned the manipulation of the char and used a State Engine to do what I wanted, instead.

I’ll have to learn that later!

I just wanted to say thanks for all the help.

You are a nice guy… for a Giants fan. :wink:

typedef enum { NONE, GOT_W, GOT_S, GOT_M, GOT_I, GOT_N, GOT_O, GOT_F } states;
char WeatherTable [6] = { 'A','B','C','D','E','F' };
char weatherValue;
char displayTemp [2];
boolean IsFarhenheit = true;
boolean IsMailMessage = false;
boolean IsWeather = false;
boolean IsSubzeroIn = false;
boolean IsSubzeroOut = false;
// current state-machine state
states state = NONE;

unsigned int currentValue;

void setup ()
{
  Serial.begin (115200);
  state = NONE;
} 

void processWeather (const unsigned int value)
{
  Serial.print ("Weather = ");
  Serial.println (value);
  weatherValue = WeatherTable[value];
} // end of processWeather

void processScale (const unsigned int value)
{
  Serial.print ("Scale = ");
  Serial.println (value);
  if (value == 1){
    IsFarhenheit = true;
  }
  else{
    IsFarhenheit = false;
  }
} // end of processScale

void processMessage (const unsigned int value)
{
  Serial.print ("Message = ");
  Serial.println (value);
  if (value == 1){
    IsMailMessage = true;
  }
  else{
    IsMailMessage = false;
  } 
}

void processIndoorTemp (const unsigned int value)
{
  Serial.print ("Indoor Temperature = ");
  Serial.println (value);
  displayTemp[0] = value; 
} // end of processIndoorTemp

void processIndoorFlag (const unsigned int value)
{
  Serial.print ("Indoor Flag = ");
  Serial.println (value);
  if (value == 1){
    IsSubzeroIn = true;
  }
  else{
    IsSubzeroIn = false;
  }
} 

void processOutdoorTemp (const unsigned int value)
{
  Serial.print ("Outdoor Temperature = ");
  Serial.println (value); 
  displayTemp [1] = value; 
}

void processOutdoorFlag (const unsigned int value)
{
  Serial.print ("Outdoor Flag = ");
  Serial.println (value);
  if (value == 1){
    IsSubzeroOut = true;
  }
  else{
    IsSubzeroOut = false;
  }
}

void handlePreviousState ()
{
  switch (state)
  {
  case GOT_W:
    processWeather (currentValue);
    break;
  case GOT_S:
    processScale (currentValue);
    break;
  case GOT_M:
    processMessage (currentValue);
    break;
  case GOT_I:
    processIndoorTemp (currentValue);
    break;
  case GOT_N:
    processIndoorFlag (currentValue);
    break;
  case GOT_O:
    processOutdoorTemp (currentValue);
    break;
  case GOT_F:
    processIndoorFlag (currentValue);
    break;    
  } 
  currentValue = 0; 
} 

void processIncomingByte (const byte c)
{
  if (isdigit (c))
  {
    currentValue *= 10;
    currentValue += c - '0';
  }  // end of digit
  else 
  {
    // The end of the number signals a state change
    handlePreviousState ();
    // set the new state, if we recognize it
    switch (c)
    {
    case 'W'://Weather
      state = GOT_W;
      break;
    case 'S'://Scale:Fahrenheit or Celsius
      state = GOT_S;
      break;
    case 'M'://Message Waiting
      state = GOT_M;
      break;
    case 'I'://Indoor Temp
      state = GOT_I;
      break;
    case 'N'://Indoor NEGATIVE FLAG
      state = GOT_I;
      break;      
    case 'O'://Outdoor Temp
      state = GOT_O;
      break;
    case 'F'://Indoor NEGATIVE FLAG
      state = GOT_I;
      break;
    default:
      state = NONE;
      break;
    }  // end of switch on incoming byte
  } // end of not digit  
} // end of processIncomingByte

void loop ()
{
  if (Serial.available ())
    processIncomingByte (Serial.read ());
  
}

Glad you found something that works.