1

I'm working on Arduino Nano and I have to use both the Bluetooth LE module Adafruit nRF8001 and ENC28J60 Ethernet module using Ethercard

The idea of the project is to receive data from smartphone via BLE and send it via Ethernet to check with server if the data is valid then the Arduino will send an ON signal out of digital pin 4

But the problem is when uart.begin() (BLE) command invoked. I can no longer use the Ethernet module anymore.

I tried remove the uart.begin() part and Ethernet works fine. I tried swap uart.begin() to run before ether.begin(). Ethernet cannot be initialized anymore.

Either way, the BLE module seems to work fine and the Arduino can respond to messages from smartphone. But sometimes it returns error code which I cannot understand. And after I pressed reset button on the Arduino it begins to work again.

ACI Command 40
Evt Cmd respone: Error. Arduino is in an while(1); loop

This version doesn't include the data verification part yet. Only send open from smartphone to trigger the Ethernet request and the server will always return you-are-good

Here is my sketch

//BLUETOOTH
#include <SPI.h>
#include "Adafruit_BLE_UART.h"

#define ADAFRUITBLE_REQ 8
#define ADAFRUITBLE_RDY 2
#define ADAFRUITBLE_RST 9

Adafruit_BLE_UART uart = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);
static bool isBTConnected = false;

//ETHERNET
#include <EtherCard.h>
#define ETH_CS 10
#define FORCE_STATIC_IP true

static const byte mymac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x31 };
byte Ethernet::buffer[140];
const char website[] PROGMEM = "192.168.1.104";
const char website_path[] PROGMEM = "/check";

//TIMER AND OUTPUT
#define OUTPUT_PIN 4
#define OUTPUT_ON  LOW
#define OUTPUT_OFF HIGH

static uint32_t timer;
static const uint16_t interval PROGMEM = 5000; // 5 seconds
static bool isOn = false;

//ETHERNET
static void ethCallback (byte status, word off, word len) {
  Serial.println(F(">>> Response"));

  Ethernet::buffer[len + off] = 0;
  Serial.print((const char*) Ethernet::buffer + off);
  Serial.println(F("..."));
  checkPermission(len + off);
}

// check if the server returns exactly string "you-are-good"
void checkPermission (word len) {
  byte c;
  uint16_t i = 0;
  uint8_t found = 0;

  const byte target[] PROGMEM = "you-are-good";
  const uint8_t targetlen PROGMEM = 12;

  do {
    c = Ethernet::buffer[i];

    if (c == target[found]) {
      if (++found >= targetlen) {
        Serial.println(F("OK"));
        outputON();
        return;
      }
    } else {
      found = 0;
    }
  } while (i++ <= len);

  Serial.println(F("NOT OK"));
  outputOFF();
}

void sendRequest() {
  Serial.println();
  Serial.println("<<< REQ ");

  char params[64];
  String prm = "?p=PARAMS_HERE";
  prm.toCharArray(params, 64);

  ether.browseUrl(website_path, params, website, ethCallback);
}

void initEthernet () {
  Serial.print(F("ETH:"));
  if (ether.begin(sizeof Ethernet::buffer, mymac, ETH_CS) == 0)
    Serial.println(F("Failed"));
  else
    Serial.println(F("OK"));

  Serial.print(F("DHCP:"));
  if (FORCE_STATIC_IP || !ether.dhcpSetup()) {
    Serial.println(F("Failed\r\nStatic: "));

    byte ip[] = {192, 168, 1, 12};
    byte gw[] = {192, 168, 1, 1};
    byte dn[] = {192, 168, 1, 1};
    byte ms[] = {255, 255, 255, 0};
    ether.staticSetup(ip, gw, dn, ms);
  } else {
    Serial.println(F("OK"));
  }

  ether.printIp(F("IP:  "), ether.myip);
  ether.printIp(F("GW:  "), ether.gwip);
  ether.printIp(F("DNS: "), ether.dnsip);

  if (!ether.dnsLookup(website)) {
    Serial.println(F("Lookup failed"));
    while (1) {
      digitalWrite(OUTPUT_PIN, HIGH);
      delay(500);
      digitalWrite(OUTPUT_PIN, LOW);
      delay(500);
    }
  }

  ether.printIp(F("SRV: "), ether.hisip);
}

//BLUETOOTH
void initBluetooth () {
  uart.setRXcallback(rxCallback);
  uart.setACIcallback(aciCallback);
  uart.setDeviceName(PSTR("BLEUART")); /* 7 characters max! */
  Serial.print(F("BT:"));
  if (uart.begin())
    Serial.println(F("OK"));
  else
    Serial.println(F("FAILED"));
}

void aciCallback(aci_evt_opcode_t event) {
  switch (event)
  {
    case ACI_EVT_DEVICE_STARTED:
      Serial.println(F("Advertising started"));
      break;
    case ACI_EVT_CONNECTED:
      isBTConnected = true;
      Serial.println(F("Connected!"));
      break;
    case ACI_EVT_DISCONNECTED:
      isBTConnected = false;
      Serial.println(F("Disconnected or advertising timed out"));
      break;
    default:
      Serial.print(F("ACI OPCODE:"));
      Serial.println(event);
      break;
  }
}

void rxCallback(uint8_t *buffer, uint8_t len) {
  uint8_t target_len = 4;
  const char* target = "open";
  uint8_t counter = 0;

  Serial.print(F("Received "));
  Serial.print(len);
  Serial.print(F(" bytes: "));
  for (int i = 0; i < len; i++) {
    char ch = (char)buffer[i];
    Serial.print(ch);
    if (ch == target[counter]) {
      counter++;
    }

    if (counter == target_len) {
      sendRequest();
    }
  }
}

//OUTPUT
void outputOFF() {
  digitalWrite(OUTPUT_PIN, LOW);
  isOn = false;

  Serial.println(F("Locked"));
}

void outputON() {
  timer = millis() + interval;
  digitalWrite(OUTPUT_PIN, HIGH);
  isOn = true;

  Serial.println(F("Unlocked"));
}

//ARDUINO
void setup () {
  pinMode(4, OUTPUT);
  Serial.begin(9600);
  Serial.println(F("BT+ETH"));

  initEthernet();
  initBluetooth();
}

void loop () {
  uart.pollACI();
  ether.packetLoop(ether.packetReceive());

  if (isOn && millis() > timer) {
    outputOFF();
  }

  // debugging commands
  if (Serial.available()) {
    char c = Serial.read();
    if (c == '0') {
      Serial.println(F("Still OK"));
    } else if (c == '1') {
      sendRequest();
    } else if (c == '2') {
      Serial.println(isBTConnected);
    }
  }
}

PS. I don't know if it has something to do with the problem. But the Arduino compiler reports that Global variables use 1,538 bytes (75%) of dynamic memory. I'm planning to get another Arduino model to make sure it works fine after I added data verification part. Don't know if it will help with the problem.

  • Check the amount of memory you need to run this sketch and library functions. My guess it that you are way over the budget (2K). – Mikael Patel Feb 3 '16 at 18:50
  • Are you toggling the slave select of the SPI slave you are not using LOW? – Avamander Feb 3 '16 at 18:58
  • @MikaelPatel, I'm not sure how to check the memory needed to run the sketch. But my guess is same as yours. – anuith Feb 4 '16 at 5:51
  • @Avamander, I don't control the SS pin myself. I don't know if the libraries of the two slaves conflicted or not. – anuith Feb 4 '16 at 5:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.