Digital Read/Write

Hello, I've looked at various ways people have connected two arduinos and from what I've read if I only want to send a signal between two boards then I can use digital read/write.

The idea is to send a HIGH signal from an adafruit Adalogger 32u4 to an adafruit feather 32u4 LoRa Radio when an event occurs. The Feather is in a waiting state until the signal changes from low to high.

I've connected it up as so:

Seeing as I'm only sending to the feather, is it ok to just have the TX of the Adalogger connected to the Feather RX and not have the other wire connected as the inverse of that?

Code for Adalogger:

void setup

int txPin = 1;
int ledPin = 13;
pinMode(ledPin, OUTPUT);
pinMode(txPin, OUTPUT)
pinMode(txPin, INPUT_PULLUP);

void function
//send interrupt
          digitalWrite(1, HIGH);
          Serial.println("Set PinH");
          digitalWrite(13, HIGH);
          delay(6000);
          digitalWrite(13, LOW);
          Serial.println("Set PinL");
          digitalWrite(1, LOW);

Code for feather:

int readPin = 0;

void checkpin
Serial.println("Waiting For Input");
        pinMode(readPin, INPUT);
        do{
        delay(1);}
        while (readPin == LOW);{
        int val = digitalRead(readPin);   // read the input pin
        {delay(1);} }
        while (readPin == HIGH){
          check = 1;
        }

        if (check == 1){
          //turn on led if signal recieved
          digitalWrite(13, HIGH);
          delay(600);
          digitalWrite(1, LOW);

What's working so far is the lighting up of the LED on the Adalogger so I can "see" the event being triggered, however the Feather is stuck in the "listening" state.

Any help would be appreciated, thanks!

There's a lot wrong with your receiving code. It looks like there are braces missing, lots of extra braces and you're missing the parenthesis on your function name.

while (readPin == LOW);{

Yeah, readPin is:

int readPin = 0;

defined to equal 0

LOW is also defined to equal 0.

So this while statement:

while (readPin == LOW);{

Will always be true and this becomes an infinite loop:

[code]while (0==0);{

And this one will never ever run

while (readPin == HIGH){
          check = 1;
        }

Delta_G:
There's a lot wrong with your receiving code. It looks like there are braces missing, lots of extra braces and you're missing the parenthesis on your function name.

while (readPin == LOW);{

Yeah, readPin is:

int readPin = 0;

defined to equal 0

LOW is also defined to equal 0.

So this while statement:

while (readPin == LOW);{

Will always be true and this becomes an infinite loop:

[code]while (0==0);{

And this one will never ever run

while (readPin == HIGH){

check = 1;
        }

The functions I just typed in just to show where the code was, so I can account for those brackets. The rest of them I've tried to tidy up a bit though!
Thank you for that. I think what I meant to do was to do was

while ((digitalRead(readPin) == LOW

If I'm working that out right its whilst the reading of the pin is LOW -> loop, then if the reading becomes HIGH, leave that while, go onto the next while (feel like this isn't the best method but anyway) and set check to 1 (to signify a change to do stuff).

I also think that I need:

int ledPin = 13;
pinMode(readPin, INPUT);
pinMode(ledPin, OUTPUT);

in the setup as otherwise I don't think the pin would be checked at all?

You should post your actual code. There is nothing more frustrating than trying to work on something that isn't the actual something you are trying to work on.

If something is wrong with your car do you take some different car to the mechanic and ask him to look at that to try to figure out what's wrong with your car? You know, just to show him how a car looks.

Sorry, I just thought that section of code would be more useful as it related to the question and it would be easier to find!

Here's the full code:

Adalogger code:

/*
  HMC5883L Triple Axis Digital Compass. Simple Example.
  Read more: http://www.jarzebski.pl/arduino/czujniki-i-sensory/3-osiowy-magnetometr-hmc5883l.html
  GIT: https://github.com/jarzebski/Arduino-HMC5883L
  Web: http://www.jarzebski.pl
  (c) 2014 by Korneliusz Jarzebski
*/

#include <Wire.h>
//#include <SD.h>
#include <SdFat.h>
#include <HMC5883L.h>
#include "RTClib.h"
RTC_DS3231 rtc;
#define ENABLE_PRINT
HMC5883L compass;
#define cardSelect 4
char fileName[] = "datalog.txt";
const int cardDetect = 7;
const int chipSelect = 4;
SdFat SD;
long mySensValsX[10] = {0,0,0,0,0,0,0,0,0,0};
long av10;
long avArray[2];
long baselineX = -186;
const long period = 600; 

void setup()
{
  #ifdef ENABLE_PRINT
  Serial.begin(115200);
  #endif
  // Initialize HMC5883L
  //Serial.println("Begin");
  while (!compass.begin())
  {
    #ifdef ENABLE_PRINT
    Serial.println("Error");
    #endif
    delay(500);
  }
  
  pinMode(cardDetect, INPUT_PULLUP);
    if (!SD.begin(chipSelect, SD_SCK_MHZ(50))) {
    #ifdef ENABLE_PRINT
    Serial.println("Card failed, or not present");
    #endif
    // don't do anything more:
    while (1);
  }
  
  #ifdef ENABLE_PRINT
  Serial.println("card initialized.");
  #endif

int txPin = 1;
int ledPin = 13;
pinMode(ledPin, OUTPUT);
pinMode(txPin, OUTPUT);
pinMode(txPin, INPUT_PULLUP);
//attachInterrupt(digitalPinToInterrupt(txPin), signal, CHANGE)

}
  
void loop()
{
  compass.begin();
  DateTime now = rtc.now();
  Vector raw = compass.readRaw();
  
  Serial.print("Av0 Read: ");
  Serial.print(avArray[0]);
  Serial.println();
  
  
  #ifdef ENABLE_PRINT
  Serial.print("X");
  Serial.print(raw.XAxis);
  //Serial.print(" ");
  //Serial.print("Y");
  //Serial.print(raw.YAxis);
  //Serial.print(" ");
  //Serial.print("Z");
  //Serial.print(raw.ZAxis); 
  //Serial.print(" "); 
  //Serial.println();//} 
  //Serial.print(now.hour(), DEC);
  //Serial.print(':');
  //Serial.print(now.minute(), DEC);
  //Serial.print(':');
  //Serial.print(now.second(), DEC);
  Serial.println();
  #endif

  //if null then fill array and get 1st average
  if (mySensValsX[0]==0 && mySensValsX[1]==0){
    Serial.println("Null, filling");
    for (int i=0; i<10; i++){
    Vector raw = compass.readRaw();
    mySensValsX[i]=raw.XAxis;
    //Serial.print("mySensValsX:");
    //Serial.print(mySensValsX[i]);
    }
    for (int j=0; j < 10; j++){
    av10 += mySensValsX[j];
    }
    av10 = (av10/10);
    avArray[0]=av10;
    avArray[1]=av10;
    }
  else {
    //shift across by 1, adding most recent at end
    Serial.println("In shift else");
  memcpy(mySensValsX, &mySensValsX[1], sizeof(mySensValsX) - sizeof(int));
  mySensValsX[9] = raw.XAxis;
  for (int i=0; i<10; i++){
  //Serial.print("mySensValsX:");
  //Serial.print(mySensValsX[i]);
  }
  
  //total and /10
  av10=0;
  for (int j=0; j < 10; j++){
    av10 += mySensValsX[j];}
    av10 = (av10/10);
    long avtemp = avArray[1];
    Serial.print("avTemp:");
    Serial.print(avtemp);
    avArray[0] = avtemp;
    avArray[1] = av10;}

  
  //debug
  Serial.print("av10: ");
  Serial.print(av10);
  Serial.println("");
  Serial.print("av[0]: ");
  Serial.print(avArray[0]);
  Serial.print(" av[1]: ");
  Serial.print(avArray[1]);
  Serial.println("");

  if ((avArray[1]<=(avArray[0]+(avArray[0]*0.05))) || (avArray[1]>=(avArray[0]-(avArray[0]*0.05)))){
    #ifdef ENABLE_PRINT
    Serial.println("Event Detected");
    Serial.println("");
    #endif
        Vector raw = compass.readRaw();
        int rawZ[10];
        for (int i=0; i<10; i++){
        rawZ[i]=raw.ZAxis;}
    //for( uint32_t tStart = millis();  (millis()-tStart) < period;  ){
    long starttime = millis();
    long endtime = starttime;
    while ((endtime - starttime) <=600){
        int avZ2;
        int avZ[2];
        Vector raw = compass.readRaw();
        memcpy(rawZ, &rawZ[1], sizeof(rawZ) - sizeof(int));
        rawZ[9] =raw.ZAxis;
        for (int j=0; j < sizeof(rawZ)- sizeof(int); j++){
        avZ2 += rawZ[j];
        avZ2 = avZ2/10;
          Serial.print("avz2: ");
          Serial.print(avZ2);
        avZ[0] = avZ[1];
        avZ[1] = avZ2;
        if (avZ[1]<=(avZ[0]+(avZ[0]*0.05)) || avZ[1]>=(avZ[0]+(avZ[0]*0.05))){
          Serial.println("Event Complete");
          //send interrupt
          digitalWrite(1, HIGH);
          Serial.println("Set PinH");
          digitalWrite(13, HIGH);
          delay(6000);
          digitalWrite(13, LOW);
          Serial.println("Set PinL");
          digitalWrite(1, LOW);
          //normalise Values to see if event is still taking place
          for (int i=0; i<10; i++){
          Vector raw = compass.readRaw();
           mySensValsX[i]=baselineX;}
          break;
        }
        else
        Serial.println("No Z");
  }break;}}
  else {
    #ifdef ENABLE_PRINT
    Serial.println("No Event");
    #endif
  }
  
  File logFile = SD.open(fileName, FILE_WRITE);
  logFile.print(raw.XAxis);
  logFile.print(", ");
  logFile.print(raw.YAxis);
  logFile.print(", ");
  logFile.print(raw.ZAxis);
  logFile.print(", ");
  logFile.print(now.hour(), DEC);
  logFile.print(':');
  logFile.print(now.minute(), DEC);
  logFile.print(':');
  logFile.print(now.second(), DEC);
  logFile.println("");
  logFile.flush();
  logFile.close();

  //delay (1000);

}

LoRa Feather code:

/*******************************************************************************
 * Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman
 *
 * Permission is hereby granted, free of charge, to anyone
 * obtaining a copy of this document and accompanying files,
 * to do whatever they want with them without any restriction,
 * including, but not limited to, copying, modification and redistribution.
 * NO WARRANTY OF ANY KIND IS PROVIDED.
 *
 *******************************************************************************/

#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#define ENABLE_PRINT

// LoRaWAN NwkSKey, network session key. string -> uint8 array
// This is the default Semtech key, which is used by the early prototype TTN
// network.
static const PROGMEM u1_t NWKSKEY[16] = {  };

// LoRaWAN AppSKey, application session key
// This is the default Semtech key, which is used by the early prototype TTN
// network.
static const u1_t PROGMEM APPSKEY[16] = {  };

// LoRaWAN end-device address (DevAddr); // <-- Change this address for every node!

// These callbacks are only used in over-the-air activation, so they are
// left empty here (we cannot leave them out completely unless
// DISABLE_JOIN is set in config.h, otherwise the linker will complain).
void os_getArtEui (u1_t* buf) { }
void os_getDevEui (u1_t* buf) { }
void os_getDevKey (u1_t* buf) { }

//static 
uint8_t mydata[] = "1C1B";

static osjob_t sendjob;

// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 1;

// Pin mapping
const lmic_pinmap lmic_pins = { 
   .nss = 8, 
   .rxtx = LMIC_UNUSED_PIN, 
   .rst = 4, 
   .dio = {7, 6, LMIC_UNUSED_PIN}, 
};

void onEvent (ev_t ev) {
    #ifdef ENABLE_PRINT
    Serial.print(os_getTime());
    #endif
    switch(ev) {
        case EV_TXCOMPLETE:
            #ifdef ENABLE_PRINT
            Serial.println(F(": TXComplete"));
            #endif
            if (LMIC.txrxFlags & TXRX_ACK)
              #ifdef ENABLE_PRINT
              Serial.println(F("Received Ack"));
              #endif
            //if (LMIC.dataLen) {
              //Serial.println(LMIC.dataLen);}
            // Schedule next transmission
            os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
            break;
         default:
            #ifdef ENABLE_PRINT
            Serial.println(F("Unknown event"));
            #endif
            break;
    }
}

void do_send(osjob_t* j){
    // Check if there is not a current TX/RX job running
    Serial.println("INdoSend");
    int readPin = 0;
    int ledPin = 13;
    pinMode(readPin, INPUT);
    pinMode(ledPin, OUTPUT);
    int check = 0;
    if (LMIC.opmode & OP_TXRXPEND) {
        #ifdef ENABLE_PRINT
        Serial.println(F("OP_TXRXPEND, not sending"));
        #endif
    } else {
        Serial.println("Waiting For Input");
        
        do{
        delay(1);
        while (readPin == LOW);{
        int val = digitalRead(readPin);   // read the input pin
        delay(1); }
        }
        while (readPin == HIGH);{
          check = 1;
        }
        
        if (check == 1){
          //turn on led if signal recieved
          digitalWrite(13, HIGH);
          delay(600);
          digitalWrite(1, LOW);
          
        // Prepare upstream data transmission at the next possible time.
        #define VBATPIN A9
        float measuredvbat = analogRead(VBATPIN);
        measuredvbat *= 2;    // we divided by 2, so multiply back
        measuredvbat *= 3.3;  // Multiply by 3.3V, our reference voltage
        measuredvbat /= 1024; // convert to voltage
        byte buffer[8];
        dtostrf(measuredvbat, 1, 2, buffer);
        String res = buffer;
        res.getBytes(buffer, res.length() + 1);
        #ifdef ENABLE_PRINT
        Serial.print("VBat: " ); Serial.println(measuredvbat);
        #endif
        LMIC_setTxData2(1, (const uint8_t*) mydata, res.length(), 60);
        #ifdef ENABLE_PRINT
        Serial.println(F("Packet queued"));
        #endif
    }
    // Next TX is scheduled after TX_COMPLETE event.

}
}


void setup() {
    delay(1000);
    #ifdef ENABLE_PRINT
    while(!Serial); 
    Serial.begin(115200);
    #endif

    // LMIC init
    os_init();
    // Reset the MAC state. Session and pending data transfers will be discarded.
    LMIC_reset();
    LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
    // Set static session parameters. Instead of dynamically establishing a session
    // by joining the network, precomputed session parameters are be provided.
    #ifdef PROGMEM
    // On AVR, these values are stored in flash and only copied to RAM
    // once. Copy them to a temporary buffer here, LMIC_setSession will
    // copy them into a buffer of its own again.
    uint8_t appskey[sizeof(APPSKEY)];
    uint8_t nwkskey[sizeof(NWKSKEY)];
    memcpy_P(appskey, APPSKEY, sizeof(APPSKEY));
    memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY));
    LMIC_setSession (0x1, DEVADDR, nwkskey, appskey);
    #else
    // If not running an AVR with PROGMEM, just use the arrays directly
    LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY);
    #endif

    //#if defined(CFG_eu868)
    // Set up the channels used by the Things Network, which corresponds
    // to the defaults of most gateways. Without this, only three base
    // channels from the LoRaWAN specification are used, which certainly
    // works, so it is good for debugging, but can overload those
    // frequencies, so be sure to configure the full frequency range of
    // your network here (unless your network autoconfigures them).
    // Setting up channels should happen after LMIC_setSession, as that
    // configures the minimal channel set.
    // NA-US channels 0-71 are configured automatically
    LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI);      // g-band
    LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    //LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK,  DR_FSK),  BAND_MILLI);      // g2-band.

    // Disable link check validation
    LMIC_setLinkCheckMode(0);

    // TTN uses SF9 for its RX2 window.
    LMIC.dn2Dr = DR_SF9;

    // Set data rate and transmit power for uplink (note: txpow seems to be ignored by the library)
    LMIC_setDrTxpow(DR_SF7,14);

    // Start job
    do_send(&sendjob);
}

void loop() {
    os_runloop_once();
}

You are on the right track with the digitalRead in reply #2 in the condition of the while. But even so.

    do {
      delay(1);
      while (readPin == LOW); {
        int val = digitalRead(readPin);   // read the input pin
        delay(1);
      }
    }
    while (readPin == HIGH); {
      check = 1;
    }

The construct is a do/while. So while(readPin == HIGH); belongs to the do and is not a while on its own. And hence the { and } around check=1; serve no purpose.

That code boils down to (simplified)

    do {
      ...
      ...
    } while (readPin == HIGH);

    check = 1;

Next in the same snippet

      while (readPin == LOW); {
        int val = digitalRead(readPin);   // read the input pin
        delay(1);
      }

Due to the semi-colon at the end of the while, the { and } are redundant.

      while (readPin == LOW);

      {
        ...
        ...
      }

and that will be equal to

      while (readPin == LOW);

        int val = digitalRead(readPin);   // read the input pin
        delay(1);

I don't think that you intended the code to work like that.

Hi,
Why do you need to communicate between Arduinos, can't one Arduino suffice?
What is your application?

Thanks.. Tom.. :slight_smile:

Thanks for the helps guys. You are correct in that I didn't intend for it to be redundant!

I put the ; after the while as I get an error telling me "expected ';' before '{' token". This was on arduino 1.6.5, however after I updated (finally) I've been able to remove the ; so I believe that's been corrected now.

I also don't think I need the do anymore so I have corrected it to this:

        //do{
        //delay(1);
        while ((digitalRead(readPin) == LOW)){
        int val = digitalRead(readPin);   // read the input pin
        delay(1); }
       // }
        while((digitalRead(readPin) == HIGH)){
          check = 1;
          Serial.println("CheckConfirmed");
        }
        
        if (check == 1){
          //turn on led if signal recieved
          digitalWrite(13, HIGH);
          delay(600);
          digitalWrite(13, LOW);}

Which seems to work! Thanks for the help

I'm using two arduinos as I wanted to record the data as well as to send it. I've also got a space limitation as the LMIC library takes up a reasonable amount of space.

Application is detecting a change in the magnetic field, record the data, then send that there is a change via LoRa