Using pin12 on the WiFi shield makes it not connect to network

Hi,

I just bought an Arduino and a new world is opening! As my first project I thought I'd build a weather station.

I've hooked up multiple sensors to my arduino uno, all working fine. But I have an issue with a barometric pressure sensor I bought from sparkfun, the MPL115A1, SparkFun Barometric Pressure Sensor Breakout - MPL115A1 - SEN-09721 - SparkFun Electronics.

I copied a piece of code I found here Arduino code for the MPL115A1 Pressure Sensor (SPI) - SparkFun Electronics Forum.

The problem is, I am running a WiFi shield between the arduino uno and this temperature sensor. Whenever I connect SDO from the barometric sensor to pin12, as the code suggests, the WiFi shield is unable to connect to my network.

After some reverse engineering of the code and reading up on the SPI interface, it seems that pin 12 (and 10+11+13) are reserved for communication between the arduino uno and the WiFi shield. Does this mean I cannot use them for anything else? I can also see that pin 7 is used for handshake and pin 4 is used for the SD card. Can it be that the WiFi shield occupies half of my digital pins?

So now I am looking for a workaround. With the other sensors connected (light, temperature 2x, humidity, wind speed, wind direction, and rain) I am running out of pins. I did some exercises in the Arduino starter kit that talked about using a shift register to allow you to connect multiple inputs to one digital pin. Can I use a shift register for pin 12 as well, to keep the barometric sensor from interfering with the WiFi shield?

Can I use a shift register for pin 12 as well, to keep the barometric sensor from interfering with the WiFi shield?

No.

That sensor is an SPI device, like the WiFi shield. You can use multiple SPI devices on the Arduino, simultaneously, as long as each one has a separate chip/slave select pin. You can connect the sensors chip select pin to any unused pin, and set that pin LOW to activate the sensor and HIGH to deactivate it.

After some reverse engineering of the code and reading up on the SPI interface, it seems that pin 12 (and 10+11+13) are reserved for communication between the arduino uno and the WiFi shield. Does this mean I cannot use them for anything else? I can also see that pin 7 is used for handshake and pin 4 is used for the SD card. Can it be that the WiFi shield occupies half of my digital pins?

6 of 20 is not quite half. The analog pins can be used as digital pins, too.

Thanks for the reply! I was not aware you could use analog pins as digital. Great!

This particular barometric sensor uses, as far as I can understand, three SPI pins: SDI, SDO and SCK. By messing around with it, it seems that only SDO is affecting the WiFi shield. Is this the only one I need to remap?

In my code, pasted below, I never set pins 11, 12 or 13. I'm having a hard time understanding what is going on, but I think it somehow selects these three pins as they are the default SPI pins. Where and how would I make it use other pins?

/*
MPL115A1 sparkfun breakout baropressure meter
 SDN       : pin 6
 CSN       : pin 9
 SDI/MOSI  : pin 11
 SDO/MISO  : pin 12
 SCK       : pin 13
*/

#include <WiFi.h>
#include <SPI.h>

//==============================//
//           Set Pins           //
//==============================//
const int    PinBaroShutDown      = 6;    // MPL115A1   Connected to SDN on barometer
const int    PinBaroChipSelectPin = 9;    // MPL115A1   Connected to CSN on barometer
const long   UpdateInterval       = 2000; // Update interval for post to server in milliseconds


//==============================//
//          Variables           //
//==============================//
float pressure; // Initialize sensor value: Pressure in hecto-pascal
char wifiSSID[] = "ssid";
char wifiPass[] = "password";

//==============================//
//    For barometric sensor     //
//==============================//
#define PRESH   0x80
#define PRESL   0x82
#define TEMPH   0x84
#define TEMPL   0x86
#define A0MSB   0x88
#define A0LSB   0x8A
#define B1MSB   0x8C
#define B1LSB   0x8E
#define B2MSB   0x90
#define B2LSB   0x92
#define C12MSB  0x94
#define C12LSB  0x96
#define CONVERT 0x24
float A0_;
float B1_;
float B2_;
float C12_;


//==============================//
//           Setup()            //
//==============================//
void setup()
{
  // Initialize serial
  Serial.begin(9600);
  
  // start the SPI library:
  SPI.begin();
  
  // Set pin modes
  pinMode(PinBaroShutDown, OUTPUT);
  digitalWrite(PinBaroShutDown, HIGH);
  pinMode(PinBaroChipSelectPin, OUTPUT);
  digitalWrite(PinBaroChipSelectPin, HIGH);
  delay (10);
    
  // read barometer registers that contain the chip-unique parameters to do the math
  unsigned int A0H = readRegister(A0MSB);
  unsigned int A0L = readRegister(A0LSB);
          A0_ = (A0H << 5) + (A0L >> 3) + (A0L & 0x07) / 8.0;
  
  unsigned int B1H = readRegister(B1MSB);
  unsigned int B1L = readRegister(B1LSB);
          B1_ = ( ( ( (B1H & 0x1F) * 0x100)+B1L) / 8192.0) - 3 ;
  
  unsigned int B2H = readRegister(B2MSB);
  unsigned int B2L = readRegister(B2LSB);
          B2_ = ( ( ( (B2H - 0x80) << 8) + B2L) / 16384.0 ) - 2 ;
  
  unsigned int C12H = readRegister(C12MSB);
  unsigned int C12L = readRegister(C12LSB);
          C12_ = ( ( ( C12H * 0x100 ) + C12L) / 16777216.0 )  ;
}

//==============================//
//           Loop()             //
//==============================//
void loop()
{
  if (status != WL_CONNECTED) //If not connected to WiFi
    connectWifi();
    
  else {
    pressure = getPressure(); // Pressure in hPa
  
    Serial.print("Pressure: ");
    Serial.println(pressure);

    delay(UpdateInterval);
  }
}


float getPressure() 
{
  // Returns a pressure reading in hPa
  
  digitalWrite(PinBaroChipSelectPin, LOW);
  delay(3);
    SPI.transfer(0x24);
    SPI.transfer(0x00);
    digitalWrite(PinBaroChipSelectPin, HIGH);
    delay(3);
  digitalWrite(PinBaroChipSelectPin, LOW);
    SPI.transfer(PRESH);
    unsigned int presH = SPI.transfer(0x00);
        delay(3);
    SPI.transfer(PRESL);
    unsigned int presL = SPI.transfer(0x00);
        delay(3);
    SPI.transfer(TEMPH);
    unsigned int tempH = SPI.transfer(0x00);
        delay(3);
    SPI.transfer(TEMPL);
    unsigned int tempL = SPI.transfer(0x00);
        delay(3);
    SPI.transfer(0x00);
      delay(3);
  digitalWrite(PinBaroChipSelectPin, HIGH);

  unsigned long press = ((presH *256) + presL)/64;
  unsigned long temp  = ((tempH *256) + tempL)/64;

  float pressure = A0_+(B1_+C12_*temp)*press+B2_*temp;
  float preshPa = (pressure*  (65.0/1023.0)+50.0) * 10;

  return(preshPa);
}

unsigned int readRegister (byte thisRegister) 
{
  //Read registers in barometer
  
  unsigned int result = 0;   // result to return
  digitalWrite(PinBaroChipSelectPin, LOW);
    delay(10);
    SPI.transfer(thisRegister);
    result = SPI.transfer(0x00);
  digitalWrite(PinBaroChipSelectPin, HIGH);
  return(result);
}

void connectWifi()
{
  // Connects the arduino to a WPA2 WiFi network
}

This particular barometric sensor uses, as far as I can understand, three SPI pins: SDI, SDO and SCK. By messing around with it, it seems that only SDO is affecting the WiFi shield. Is this the only one I need to remap?

You can't. The SPI pins are fixed in hardware. As I said, you can have any number of devices connected to the SPI pins at one time, as long as each has a separate slave/chip select pin.

The WiFi shield uses pin 10 as the slave select pin. The pressure sensor can use any unused pin as it's slave select pin (as long as the corresponding pin on the pressure sensor is connected to that pin on the Arduino).

In my code, pasted below, I never set pins 11, 12 or 13.

Yes, you did. Right here:

#include <SPI.h>

Where and how would I make it use other pins?

You don't.

PaulS:

This particular barometric sensor uses, as far as I can understand, three SPI pins: SDI, SDO and SCK. By messing around with it, it seems that only SDO is affecting the WiFi shield. Is this the only one I need to remap?

You can't. The SPI pins are fixed in hardware. As I said, you can have any number of devices connected to the SPI pins at one time, as long as each has a separate slave/chip select pin.

The WiFi shield uses pin 10 as the slave select pin. The pressure sensor can use any unused pin as it's slave select pin (as long as the corresponding pin on the pressure sensor is connected to that pin on the Arduino).

Again, thanks for the reply!

Hmmm... I am currently using the following pins for my barometric sensor:
pin8 as sleep/shutdown
pin9 as chip select
pin11 as serial data in
pin12 as serial data out
pin13 as serial clock

Shouldn't this in theory work fine with the wifi shield? Any tips on troubleshooting this?

Any tips on troubleshooting this?

The usual one. Post your code!

Okay, here it goes, this is my complete code. (trimmed to match the 9500 max characters of forum posts) Also bare in mind that this is my first Arduino code ever, so any suggestions are highly appreciated :slight_smile:

#include <WiFi.h>
#include <SPI.h>
#include <TextFinder.h>
#include <OneWire.h> 

//==============================//
//           Set Pins           //
//==============================//
const int    PinTempIn            = A0;                         // TMP36      Inside temperature sensor (sparkfun.com/products/10988)
const int    PinLight             = A1;                         // Temt6000   Outside light sensor (sparkfun.com/products/8688)
const int    PinHumid             = A2;                         // HIH-4030   Outsude humidity sensor (sparkfun.com/products/9569)
const int    PinVane              = A5;                         // SEN-08942  Wind vane (wind direction) (sparkfun.com/products/8942)
const int    PinAnemometer        = 2;                          // SEN-08942  Wind speed pin (interupt) (sparkfun.com/products/8942)
const int    PinRainMeter         = 3;                          // SEN-08942  Rain meter (interupt) (sparkfun.com/products/8942)
const int    PinTempOut           = 5;                          // DS18B20    Outside temperature sensor signal pin (sparkfun.com/products/11050)
const int    PinBaroShutDown      = 6;                          // MPL115A1   Connected to SDN on barometer (sparkfun.com/products/9721)
const int    PinWiFiDoNotUse      = 7;                          // DEV11287   Reminder to not use. Already used by WiFi hadshake (sparkfun.com/products/11287)
const int    PinLEDpost           = 8;                          // LED        That turns red if post to server was unsuccessful
const int    PinBaroChipSelectPin = 9;                          // MPL115A1   Connected to CSN on barometer
const int    PinWifiDoNotUse2     = 10;                         // DEV11287   Reminder to not use. Already used by WiFi chip select (sparkfun.com/products/11287)


//==============================//
//            Config            //
//==============================//
char         wifiSSID[]           = "a";   // Network SSID 
char         wifiPass[]           = "b";   // Network password
char         server[]             = "c";   // Server of the target php script
char         url[]                = "d";   // Local server URL to php script 
char         serverSecret[]       = "e";   // Secret for posting data to php script on the server
char         location[]           = "f";   // Name of location 
float        latitude             = 1.1;   // Latitude of location
float        longitude            = 2.2;   // Longitude of location
const long   UpdateInterval       = 10000; // Update interval for post to server in milliseconds

//==============================//
//      Interupt Cpunters       //
//==============================//
volatile int numRevsAnemometer    = 0;                          // Incremented in the interrupt of pulse from wind speed sensor
volatile int numRainClicks        = 0;                          // Incremented in the interrupt of pulse from rain sensor

//==============================//
//     Initialize variables     //
//==============================//
float        tempIn;
float        tempOut;
int          light;
float        rHumidity;
float        pressure;
String       wind_direction;
float        wind_speed;
float        rainfall;
WiFiClient   client;
TextFinder   finder(client);
OneWire      ds(PinTempOut); // Initialise the outside temperature sensor
int          status               = WL_IDLE_STATUS;

//==============================//
//    For barometric sensor     //
//==============================//
#define PRESH   0x80
#define PRESL   0x82
#define TEMPH   0x84
#define TEMPL   0x86
#define A0MSB   0x88
#define A0LSB   0x8A
#define B1MSB   0x8C
#define B1LSB   0x8E
#define B2MSB   0x90
#define B2LSB   0x92
#define C12MSB  0x94
#define C12LSB  0x96
#define CONVERT 0x24
float A0_;
float B1_;
float B2_;
float C12_;

void setup()
{
  // Initialize serial
  Serial.begin(9600);
  
  // start the SPI library:
  SPI.begin();
  
  // Set pin modes
  pinMode(PinLEDpost, OUTPUT);
  pinMode(PinRainMeter, INPUT);
  digitalWrite(PinRainMeter, HIGH);
  pinMode(PinAnemometer, INPUT);
  digitalWrite(PinAnemometer, HIGH);
  pinMode(PinBaroShutDown, OUTPUT);
  digitalWrite(PinBaroShutDown, HIGH);
  pinMode(PinBaroChipSelectPin, OUTPUT);
  digitalWrite(PinBaroChipSelectPin, HIGH);
  delay (10);
  
  // Initialize interupts
  attachInterrupt(0, countAnemometer, FALLING);
  attachInterrupt(1, countRainClicks, FALLING);
  
  // read barometer registers that contain the chip-unique parameters to do the math
  unsigned int A0H = readRegister(A0MSB);
  unsigned int A0L = readRegister(A0LSB);
          A0_ = (A0H << 5) + (A0L >> 3) + (A0L & 0x07) / 8.0;
  
  unsigned int B1H = readRegister(B1MSB);
  unsigned int B1L = readRegister(B1LSB);
          B1_ = ( ( ( (B1H & 0x1F) * 0x100)+B1L) / 8192.0) - 3 ;
  
  unsigned int B2H = readRegister(B2MSB);
  unsigned int B2L = readRegister(B2LSB);
          B2_ = ( ( ( (B2H - 0x80) << 8) + B2L) / 16384.0 ) - 2 ;
  
  unsigned int C12H = readRegister(C12MSB);
  unsigned int C12L = readRegister(C12LSB);
          C12_ = ( ( ( C12H * 0x100 ) + C12L) / 16777216.0 )  ;
}

void loop()
{
  if (status != WL_CONNECTED) //If not connected to WiFi
    connectWifi();
    
  else {
    tempIn         = getTempIn();                      // Temperature inside in celcius
    tempOut        = getTempOut();                     // Temperature outside in celsius
    light          = getLight();                       // 0-1023. Need to translate into useful info
    pressure       = getPressure();                    // Pressure in hPa
    wind_direction = getWindDirection();               // Wind direction in one or two character string (N, NE, ...)
    wind_speed     = getWindSpeed();                   // Wind speed in meters per second
    rainfall       = getRain();                        // Rain in millimeters
    rHumidity      = getRelativeHumidity(tempOut);     // Relative humidity in percentage
   
    postToServer();
  }
  delay(UpdateInterval);
}

float getTempIn() 
{
  // Returns the temperature from the SEN-10988 outside thermometer in DEG Celsius
}

float getTempOut() 
{
  // Returns the temperature from the DS18S20 outside thermometer in DEG Celsius
}

int getLight() 
{
  // Returns a 0-1023 value for light measured on the Temt6000 light sensor
}

String getWindDirection() 
{
  // Returns a string representing the direction that the wind vane is pointing at
}

float getWindSpeed() 
{
  // Returns a wind speed in meters per second from the anemometer
}

float getRelativeHumidity (float degreesCelsius) 
{
  // Returns a relative air humidity based on measurement from outside temperature sensor in percentage
}

float getPressure() 
{
  // Returns a pressure reading in hPa
  
  digitalWrite(PinBaroChipSelectPin, LOW);
  delay(3);
    SPI.transfer(0x24);
    SPI.transfer(0x00);
    digitalWrite(PinBaroChipSelectPin, HIGH);
    delay(3);
  digitalWrite(PinBaroChipSelectPin, LOW);
    SPI.transfer(PRESH);
    unsigned int presH = SPI.transfer(0x00);
        delay(3);
    SPI.transfer(PRESL);
    unsigned int presL = SPI.transfer(0x00);
        delay(3);
    SPI.transfer(TEMPH);
    unsigned int tempH = SPI.transfer(0x00);
        delay(3);
    SPI.transfer(TEMPL);
    unsigned int tempL = SPI.transfer(0x00);
        delay(3);
    SPI.transfer(0x00);
      delay(3);
  digitalWrite(PinBaroChipSelectPin, HIGH);

  unsigned long press = ((presH *256) + presL)/64;
  unsigned long temp  = ((tempH *256) + tempL)/64;

  float pressure = A0_+(B1_+C12_*temp)*press+B2_*temp;
  float preshPa = (pressure*  (65.0/1023.0)+50.0) * 10;

  return(preshPa);
}

float getRain() 
{
  // Returns rain measured in last period in millimeters
}

void connectWifi()
{
  // Connects the arduino to a WPA2 WiFi network as defined above
  
  // attempt to connect using WPA2 encryption:
  Serial.println("Attempting to connect to WPA network...");
  status = WiFi.begin(wifiSSID, wifiPass);
  
  // wait for connection:
  delay(5000);

  // if you're not connected, stop here:
  if ( status != WL_CONNECTED) { 
    Serial.println("Couldn't get a wifi connection");
    Serial.println();
  } 
  // if you are connected, print out info about the connection:
  else {
    Serial.print("Connected to network ");
    Serial.println(wifiSSID);
    Serial.println();
  }
}

void postToServer() 
{
  // Posts results to URL as defined above
}

void countAnemometer() 
{
  // Helper method for the interupt of wind speed. Called each time the reed switch triggers (one revolution).
}

unsigned int readRegister (byte thisRegister) 
{
  //Read registers in barometer
  
  unsigned int result = 0;   // result to return
  digitalWrite(PinBaroChipSelectPin, LOW);
    delay(10);
    SPI.transfer(thisRegister);
    result = SPI.transfer(0x00);
  digitalWrite(PinBaroChipSelectPin, HIGH);
  return(result);
}

void countRainClicks() 
{
  // Interrupt handler for rain meter. Called each time the bucket tips
}

Also, a simple wiring diagram:

//==============================//
//            Wiring            //
//==============================//

ARDUINO     BREADBOARD 1                                                 BREADBOARD 2
3.3v
5v----------5v rail--------------rj45-------C-A-T-5--------rj45----------5v rail
GND---------GND rail-------------rj45-------C-A-T-5--------rj45----------GND rail
VIN
A0----------TMP36 Temp sensor
A1-------------------------------rj45-------C-A-T-5--------rj45----------TEMT6000  Light sensor
A2-------------------------------rj45-------C-A-T-5--------rj45----------HIH-4030  Humidity sensor
A3
A4
A5-------------------------------rj45-------C-A-T-5--------rj45----------SEN-08942 Wind Vane
0
1
2--------------------------------rj45-------C-A-T-5--------rj45----------SEN-08942 Anenometer (wind speed)
3--------------------------------rj45-------C-A-T-5--------rj45----------SEN-08942 Rain meter
4
5--------------------------------rj45-------C-A-T-5--------rj45----------DS18B20  Temperature sensor
6--------------------------------rj45-------C-A-T-5--------rj45----------MPL115A1 Barometer sleep
7
8----------LED
9--------------------------------rj45-------C-A-T-5--------rj45----------MPL115A1 Barometer chip select
10
11-------------------------------rj45-------C-A-T-5--------rj45----------MPL115A1 Barometer SDI
12-------------------------------rj45-------C-A-T-5--------rj45----------MPL115A1 Barometer SDO
13-------------------------------rj45-------C-A-T-5--------rj45----------MPL115A1 Barometer SCK
GND
AREF
SDA
SCL

Your function to get the data from the barometric sensor correctly toggles the chip select pin for that sensor BUT it fails to set the other chip select pin, for the other the SPI device. It needs to set pin 10 HIGH and LOW at the appropriate times. I can never remember whether it is HIGH to activate or to deactivate. Set pin 10 HIGH at the start of the function, and LOW at the end. If that doesn't work, change which way the pin is set at the start and the end of the function.

PaulS:
Your function to get the data from the barometric sensor correctly toggles the chip select pin for that sensor BUT it fails to set the other chip select pin, for the other the SPI device. It needs to set pin 10 HIGH and LOW at the appropriate times. I can never remember whether it is HIGH to activate or to deactivate. Set pin 10 HIGH at the start of the function, and LOW at the end. If that doesn't work, change which way the pin is set at the start and the end of the function.

Spot on! That is probably it!

So, I set the WiFi shield select pin to low/high, to tell it that now the barometric sensor wants to communicate, then when the barometric sensor has finished reading the data, I set the WiFi shield select pin back to the original setting? I think the penny just dropped :slight_smile:

I've spent some time trying to debug, but not going anywhere. Setting the select pin for the barometer to HIGH (which should disable it) doesn't seem to do much.

The error code I get is that the wifi shield is not present. I'm now just playing with a simple code to see if I can get it to connect to my wifi. This is my code, same wiring as before.

#include <WiFi.h>

char ssid[] = "a?";     //  your network SSID (name) 
char pass[] = "b";  // your network password
int status = WL_IDLE_STATUS;     // the Wifi radio's status

void setup() {
  Serial.begin(9600);
  
  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present"); 
    // don't continue:
    while(true);
  } 
  
 // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) { 
    Serial.print("Attempting to connect to WPA SSID: "); 
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
   
  // you're connected now, so print out the data:
  Serial.print("You're connected to the network");
}

void loop() {
  delay(10000);
}

Which outputs "WiFi shield not present".

Inserting the following at the beginning of the setup() method does nothing:

  pinMode(9, OUTPUT); // Connected to the select pin of the barometer
  digitalWrite(9, HIGH);

By unplugging pin 12 from my barometer (barometer SDO), everything works fine (except I don't get a barometer reading that is).

I'm struggling here. Am I missing something?

FINALLY found out what was wrong!

It turns out that this phenomenon only happens when I try to connect the barometric sensor through the CAT5 cable. When I connect it right on the breadboard next to the Arduino, all is fine.

I have no clue why this is. I have checked, rechecked, and checked again all connections. They are fine. The cable is tested and is fine. The RJ45 connectors are fine. Does simply running the signal through the CAT5 cable do something mysterious to the signal somehow?

Could be the load on the line. Try putting a 1K pullup on pin 12 close to the Arduino.