Zahlenwerte über I2C senden

Hallo,

ich möchte einen Temperaturwert von einen NANO auf einen UNO senden.

Im Forum und im WWW habe ich schon "alles" durchsucht, aber leider nicht wirklich etwas gefunden was funktioniert:-(

Code Slave

// Wire Slave Sender
// by Nicholas Zambetti <http://www.zambetti.com>

// Demonstrates use of the Wire library
// Sends data as an I2C/TWI slave device
// Refer to the "Wire Master Reader" example for use with this

// Created 29 March 2006

// This example code is in the public domain.


#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2 /* Digitalport Pin 2 definieren */

OneWire ourWire(ONE_WIRE_BUS); /* Ini oneWire instance */
int temp = 0;
DallasTemperature sensors(&ourWire);/* Dallas Temperature Library für Nutzung der oneWire Library vorbereiten */

void setup()
{
  Serial.begin(9600);
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event

  sensors.begin();/* Inizialisieren der Dallas Temperature library */
}


void loop()
{
  delay(100);

  sensors.requestTemperatures(); // Temp abfragen

  float t = sensors.getTempCByIndex(0);
  char buffer1[10];
  String temp = dtostrf(t, 8, 0, buffer1);
  Serial.println(t);
}
// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent()
{
  Wire.write(temp); // respond with message of 6 bytes
  // as expected by master
}

Code Master

// Wire Master Reader
// by Nicholas Zambetti <http://www.zambetti.com>

// Demonstrates use of the Wire library
// Reads data from an I2C/TWI slave device
// Refer to the "Wire Slave Sender" example for use with this

// Created 29 March 2006

// This example code is in the public domain.


#include <Wire.h>

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
}

void loop()
{
  Wire.requestFrom(8,10);    // request 6 bytes from slave device #8

  while (Wire.available())   // slave may send less than requested
  {
    char c = Wire.read(); // receive a byte as character
    Serial.print(c);         // print the character
  }

  delay(500);
}

Kann mir jemand einen kleinen Wink mit einer Laterne geben was ich vergessen habe oder falsch mache ?:slight_smile:

MfG Mario

Mehrere Fehler....

Fangen wir mal mit dem ersten an:

Wire.write(temp);

Wo füllst du temp ?

Vorsicht mit Wire.write(). Das ist eine Falle. Damit kann man entweder ein Byte oder ein Array senden. Wenn man da einen int oder long übergibt wird der einfach auf ein Byte gecastet. Das kann so also nicht gehen.
Allerdings geht im Request Event Handler nur ein einziges mal write() wodurch man nicht einfach mehrere Bytes senden kann

Ohne Strings, direkt mit Zahlen:

http://forum.arduino.cc/index.php?topic=407599.msg2804476#msg2804476

Die Data Union entsprechend anpassen! Wenn du nur einen Wert hast brauchst du das anonyme struct darin nicht. Für einen int geht einfach das:

union Data
{
  byte asArray[sizeof(int)];
  int temp;
};

Das ist Test/Demo-Code! Es wird gezeigt wie der Master Daten an den Slave schickt. Aber auch wie der Master vom Slave Daten anfordert. In dem Beispiel schickt der Master zwei Zahlen, der Slave inkrementiert sie und der Master liest sie sofort wieder zurück. Praktisch musst du dich für eine Variante entscheiden!

1.) Master schickt Daten an den Slave:
Auf dem Master writeValues() nehmen und auf dem Slave den Receive Event Handler

2.) Master fordert Daten vom Slave an (analog zu I2C Sensoren):
Auf dem Master getValues() verwenden und auf dem Slave den Request Event Handler

Die Idee dahinter ist dass in einer Union alle Variablen den gleichen Speicherplatz belegen. Wenn man also auf das Array Byte für Byte schreibt, schreibt man gleichzeitig in die eigentliche Variable. Und beim Lesen genauso. Man kann also Variablen sowohl als Array als auch als Integer/Float ansprechen

Ich habe das mit der EasyTransferI2C.h Library gelöst.
Funktioniert gut und recht unkompliziert.

Ich danke euch erstmal für eure Hilfe.

Zunächst möchte ich euch mein eigentliches vorhaben erklären.

Ich verwende für meine Haussteuerung FHEM, welches auf einem Netbook läuft, dann gibt es z.B. im Gewächshaus einen Arduino Mega (mit Configurable Firmata)der über ein Ethernetshield mit dem "Server" kommuniziert.
Nun habe ich einen Wind und Regenmesser gebaut der die Daten über einen Arduino Nano (verbunden mit dem Mega über I2C) an FHEM senden soll.

Bevor ich mich an dieses Projekt wage wollte ich erstmal mit I2c mich vertraut machen:-)

Zunächst muss ich noch herausfinden in welcher Form FHEM die Daten auch verarbeiten kann.

Kennt ihr FHEM?

Wenn es darum geht Daten von einem Arduino an einen anderen zu senden ist es egal was mit den Daten danach geschieht. Das hat eigentlich nichts miteinander zu tun. Du kannst das auf dem anderen Ende erstmal auf der seriellen Schnittstelle ausgeben.

Du musst halt zwei Eigenheiten der Wire Library beachten:
1.) Man kann nur entweder ein Byte oder ein Array senden. Man kann nicht direkt Multi-Byte Variablen schicken!
2.) Man kann im Request Event Handler nur einmal write() machen

Beides macht es sehr attraktiv das mit Unions zu handhaben. Es gibt noch eine andere Variante (Zeiger und Casts), aber das ist für Anfänger schwer verständlich

Wie weit sind die beiden Arduinos eigentlich voneinander entfernt?

FHEM hab ich auf einem Raspberry am Laufen an dem meine Heizung hängt, eine Wetterstation soll noch folgen....

Das Problem ist dass ich auf dem anderen Arduino nicht einfach über einen serielle Schnittstelle auslesen kann.
Auf dem Mega (der die Daten Windgeschwindigkeit und Regenmenge empfangen soll) ist die Confugurable Firmata.
Ich glaube nicht dass es egal ist in welcher form die Daten ankommen.

Die beiden Arduino`s sind circa 15 cm auseinander.

Ich möchte den Nano zum verarbeiten der Sensorwerte verwenden da sonst die Kommunikation auf dem Netztwerk bei einer Windgeschwindigkeit von 50 Kmh und 12 Impulsen pro Umdrehung zu stark wäre und es zu Messfehlern führen würde oder wiedermal das Ethernetshield den Dienst verweigert :confused:

mario01:
Ich glaube nicht dass es egal ist in welcher form die Daten ankommen.

Wenn FHEM ein bestimmtes Format möchte kannst du das nach dem Empfang umsetzten. Am einfachsten ist es jedenfalls den Wert einfach als Integer oder evtl. Float zu übertragen

Dann sollte ich die "Union Data" Variante weiter verfolgen. Oder?

Das ist die Configurable Firmata

#include <Firmata.h>
#include <SPI.h>
#include <Ethernet.h>

/*
 * To configure 'Network Firmata' to use an ENC28J60 based board include
 * 'UIPEthernet.h' (no SPI.h required). The UIPEthernet-library can be downloaded
 * from: https://github.com/ntruchsess/arduino_uip
 */

//#include <UIPEthernet.h>

/*
 * To execute Network Firmata on Yun uncomment Bridge.h and YunClient.h.
 * Do not include Ethernet.h or SPI.h in this case.
 * On Yun there's no need to configure local_ip and mac in the sketch
 * as this is configured on the linux-side of Yun.
 */

//#include <Bridge.h>
//#include <YunClient.h>

#if defined ethernet_h || defined UIPETHERNET_H || defined _YUN_CLIENT_H_
/*==============================================================================
 * Network configuration for Network Firmata
 *============================================================================*/
#define NETWORK_FIRMATA
//replace with ip of server you want to connect to, comment out if using 'remote_host'
#define remote_ip IPAddress(192,168,0,150)
//replace with hostname of server you want to connect to, comment out if using 'remote_ip'
//#define remote_host "server.local"
//replace with the port that your server is listening on
#define remote_port 3232
//replace with arduinos ip-address. Comment out if Ethernet-startup should use dhcp. Is ignored on Yun
#define local_ip IPAddress(192,168,0,152)
//replace with ethernet shield mac. It's mandatory every device is assigned a unique mac. Is ignored on Yun
const byte mac[] = {0x90, 0xA2, 0xDA, 0x0D, 0x07, 0x02};
#endif

// To configure, save this file to your working directory so you can edit it
// then comment out the include and declaration for any features that you do
// not need below.

// Also note that the current compile size for an Arduino Uno with all of the
// following features enabled is about 22.4k. If you are using an older Arduino
// or other microcontroller with less memory you will not be able to include
// all of the following feature classes.

#include <utility/DigitalInputFirmata.h>
DigitalInputFirmata digitalInput;

#include <utility/DigitalOutputFirmata.h>
DigitalOutputFirmata digitalOutput;

#include <utility/AnalogInputFirmata.h>
AnalogInputFirmata analogInput;

#include <utility/AnalogOutputFirmata.h>
AnalogOutputFirmata analogOutput;

#include <Servo.h> //wouldn't load from ServoFirmata.h in Arduino1.0.3
#include <utility/ServoFirmata.h>
ServoFirmata servo;

#include <Wire.h> //wouldn't load from I2CFirmata.h in Arduino1.0.3
#include <utility/I2CFirmata.h>
I2CFirmata i2c;

#include <utility/OneWireFirmata.h>
OneWireFirmata oneWire;

#include <utility/StepperFirmata.h>
StepperFirmata stepper;

#include <utility/FirmataExt.h>
FirmataExt firmataExt;

#include <utility/FirmataScheduler.h>
FirmataScheduler scheduler;

#include <utility/EncoderFirmata.h>
EncoderFirmata encoder;


// dependencies. Do not comment out the following lines
#if defined AnalogOutputFirmata_h || defined ServoFirmata_h
#include <utility/AnalogWrite.h>
#endif

#if defined AnalogInputFirmata_h || defined I2CFirmata_h || defined EncoderFirmata_h
#include <utility/FirmataReporting.h>
FirmataReporting reporting;
#endif

// dependencies for Network Firmata. Do not comment out.
#ifdef NETWORK_FIRMATA
#if defined remote_ip && defined remote_host
#error "cannot define both remote_ip and remote_host at the same time!"
#endif
#include <utility/EthernetClientStream.h>
#ifdef _YUN_CLIENT_H_
YunClient client;
#else
EthernetClient client;
#endif
#if defined remote_ip && !defined remote_host
#ifdef local_ip
EthernetClientStream stream(client, local_ip, remote_ip, NULL, remote_port);
#else
EthernetClientStream stream(client, IPAddress(0, 0, 0, 0), remote_ip, NULL, remote_port);
#endif
#endif
#if !defined remote_ip && defined remote_host
#ifdef local_ip
EthernetClientStream stream(client, local_ip, IPAddress(0, 0, 0, 0), remote_host, remote_port);
#else
EthernetClientStream stream(client, IPAddress(0, 0, 0, 0), IPAddress(0, 0, 0, 0), remote_host, remote_port);
#endif
#endif
#endif

/*==============================================================================
 * FUNCTIONS
 *============================================================================*/

void systemResetCallback()
{
  // initialize a defalt state

  // pins with analog capability default to analog input
  // otherwise, pins default to digital output
  for (byte i = 0; i < TOTAL_PINS; i++) {
    if (IS_PIN_ANALOG(i)) {
#ifdef AnalogInputFirmata_h
      // turns off pullup, configures everything
      Firmata.setPinMode(i, ANALOG);
#endif
    } else if (IS_PIN_DIGITAL(i)) {
#ifdef DigitalOutputFirmata_h
      // sets the output to 0, configures portConfigInputs
      Firmata.setPinMode(i, OUTPUT);
#endif
    }
  }

#ifdef FirmataExt_h
  firmataExt.reset();
#endif
}


void setup()
{
  
#ifdef NETWORK_FIRMATA
#ifdef _YUN_CLIENT_H_
  Bridge.begin();
#else
#ifdef local_ip
  Ethernet.begin((uint8_t *)mac, local_ip); //start ethernet
#else
  Ethernet.begin((uint8_t *)mac); //start ethernet using dhcp
#endif
#endif
  delay(1000);
#endif
  Firmata.setFirmwareVersion(FIRMATA_MAJOR_VERSION, FIRMATA_MINOR_VERSION);

#if defined AnalogOutputFirmata_h || defined ServoFirmata_h
  /* analogWriteCallback is declared in AnalogWrite.h */
  Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
#endif

#ifdef FirmataExt_h
#ifdef DigitalInputFirmata_h
  firmataExt.addFeature(digitalInput);
#endif
#ifdef DigitalOutputFirmata_h
  firmataExt.addFeature(digitalOutput);
#endif
#ifdef AnalogInputFirmata_h
  firmataExt.addFeature(analogInput);
#endif
#ifdef AnalogOutputFirmata_h
  firmataExt.addFeature(analogOutput);
#endif
#ifdef ServoFirmata_h
  firmataExt.addFeature(servo);
#endif
#ifdef I2CFirmata_h
  firmataExt.addFeature(i2c);
#endif
#ifdef OneWireFirmata_h
  firmataExt.addFeature(oneWire);
#endif
#ifdef StepperFirmata_h
  firmataExt.addFeature(stepper);
#endif
#ifdef FirmataReporting_h
  firmataExt.addFeature(reporting);
#endif
#ifdef FirmataScheduler_h
  firmataExt.addFeature(scheduler);
#endif
#ifdef EncoderFirmata_h
  firmataExt.addFeature(encoder);
#endif
#endif
  /* systemResetCallback is declared here (in ConfigurableFirmata.ino) */
  Firmata.attach(SYSTEM_RESET, systemResetCallback);

  // Network Firmata communicates with Ethernet-shields over SPI. Therefor all
  // SPI-pins must be set to IGNORE. Otherwise Firmata would break SPI-communication.
  // add Pin 10 and configure pin 53 as output if using a MEGA with Ethernetshield.
  // No need to ignore pin 10 on MEGA with ENC28J60, as here pin 53 should be connected to SS:
#ifdef NETWORK_FIRMATA
  // ignore SPI and pin 4 that is SS for SD-Card on Ethernet-shield
  for (byte i = 0; i < TOTAL_PINS; i++) {
    if (IS_PIN_SPI(i)
        || 4 == i
        // || 10==i //explicitly ignore pin 10 on MEGA as 53 is hardware-SS but Ethernet-shield uses pin 10 for SS
       ) {
      Firmata.setPinMode(i, IGNORE);
    }
  }
  //  pinMode(PIN_TO_DIGITAL(53), OUTPUT); configure hardware-SS as output on MEGA
  pinMode(PIN_TO_DIGITAL(4), OUTPUT); // switch off SD-card bypassing Firmata
  digitalWrite(PIN_TO_DIGITAL(4), HIGH); // SS is active low;

  // start up Network Firmata:
  Firmata.begin(stream);
#else
  // start up the default Firmata using Serial interface:
  Firmata.begin(57600);
#endif
  systemResetCallback();  // reset to default config
}

void loop()
{
  
#ifdef DigitalInputFirmata_h
  digitalInput.report();
#endif
  while (Firmata.available()) {
    Firmata.processInput();
#ifdef FirmataScheduler_h
    if (!Firmata.isParsingMessage()) {
      goto runtasks;
    }
  }
  if (!Firmata.isParsingMessage()) {
runtasks: scheduler.runTasks();
#endif
  }

#ifdef FirmataReporting_h
  if (reporting.elapsed()) {
#ifdef AnalogInputFirmata_h
    analogInput.report();
#endif
#ifdef I2CFirmata_h
    // report i2c data for all device with read continuous mode enabled
    i2c.report();
#endif
#ifdef EncoderFirmata_h
    // report encoders positions if reporting enabled.
    encoder.report();
#endif
  }
#endif
#ifdef StepperFirmata_h
  stepper.update();
#endif
#if defined NETWORK_FIRMATA && !defined local_ip &&!defined _YUN_CLIENT_H_
  if (Ethernet.maintain())
  {
    stream.maintain(Ethernet.localIP());
  }
#endif
}

Du hast gefragt wie I2C Kommunikation funktioniert und wolltest das verstehen. Dann beschränke dich erst mal darauf. Ich habe dir Demo-Code gegeben, den du selbst anpassen musst. Entweder so dass der Master Daten sendet oder Daten vom Slave anfordert. Also lass den anderen Kram erst mal komplett weg und schau dass du das verstehst.

Wenn das denn geht kannst du es mit dem anderen Zeug kombinieren

Brauchst du die Firmata überhaupt? Was eigenes wäre viel kleiner und verständlicher. Das Beispiel "WebClient" bringt schon alles mit um FHEM Daten bereitzustellen. Schau mal hier rein:

Temperaturdaten an FHEM

Gruß

Ich habe nun ein bisschen herum probiert und habe nun als Rückmeldung " Master:
0 "

Irgendetwas habe ich übersehen :disappointed_relieved:

MASTER:

#include <Wire.h>
int led=13;
union Data
{
  byte asArray[sizeof(int)];
  int temp;
};

Data slaveOne;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  
}

void loop()
{
  
  if (getValues(1, slaveOne))    //Daten anfordern
  {
    Serial.println("Master:");
    Serial.println(slaveOne.temp);
   
    Serial.println();
 
  }
  
  delay(1000);
}

void writeValues(byte slave, union Data& values)
{
  Wire.beginTransmission(slave);
  Wire.write(values.asArray, sizeof(values));
  Wire.endTransmission();
}

bool getValues(byte slave, union Data& values)
{
  Wire.requestFrom(slave, sizeof(values));
    
  if (Wire.available() > 0)
  {
    for (unsigned int i = 0; i < sizeof(values); i++)
      values.asArray[i] = Wire.read();

    return true;
  }
  else
    return false;
}

Slave:

#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2 /* Digitalport Pin 2 definieren */

OneWire ourWire(ONE_WIRE_BUS); /* Ini oneWire instance */

DallasTemperature sensors(&ourWire);/* Dallas Temperature Library für Nutzung der oneWire Library vorbereiten */

union Data
{
 byte asArray[sizeof(int)];
  int temp=sensors.getTempCByIndex(0);
};

Data values;

void setup() 
{
  Wire.begin(1);
Serial.begin(9600);
    
  Wire.onRequest(requestHandler);
 


  sensors.begin();/* Inizialisieren der Dallas Temperature library */
}

void loop() 
{
  sensors.requestTemperatures(); // Temp abfragen


}



void requestHandler()
{
  //hier geht nur einmal write() !!
  
  Wire.write(values.asArray, sizeof(values));
}
union Data
{
 byte asArray[sizeof(int)];
  int temp=sensors.getTempCByIndex(0);
};

Das hat da nichts zu suchen. Das Auslesen der Temperatur gehört in loop(). Erst macht man requestTemperatures() um eine Messung zu starten. Danach liest man die Temperatur aus.

values.temp = sensors.getTempCByIndex(0);

Und writeValues() kann auf dem Master bei der Variante entfallen

Vielen dank :slight_smile:

Es funktioniert.

Master:

#include <Wire.h>
int led=13;
union Data
{
  byte asArray[sizeof(int)];
  int temp;
};

Data slaveOne;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  
}

void loop()
{
  
  if (getValues(1, slaveOne))    //Daten anfordern
  {
    Serial.println("Master:");
    Serial.println(slaveOne.temp);
   
    Serial.println();
 
  }
  
  delay(1000);
}



bool getValues(byte slave, union Data& values)
{
  Wire.requestFrom(slave, sizeof(values));
    
  if (Wire.available() > 0)
  {
    for (unsigned int i = 0; i < sizeof(values); i++)
      values.asArray[i] = Wire.read();

    return true;
  }
  else
    return false;
}

Slave:

#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2 /* Digitalport Pin 2 definieren */

OneWire ourWire(ONE_WIRE_BUS); /* Ini oneWire instance */

DallasTemperature sensors(&ourWire);/* Dallas Temperature Library für Nutzung der oneWire Library vorbereiten */

union Data
{
 byte asArray[sizeof(int)];
  int temp;
};

Data values;

void setup() 
{
  Wire.begin(1);
Serial.begin(9600);
    
  Wire.onRequest(requestHandler);
 


  sensors.begin();/* Inizialisieren der Dallas Temperature library */
}

void loop() 
{
  sensors.requestTemperatures(); // Temp abfragen

  values.temp=sensors.getTempCByIndex(0);

}



void requestHandler()
{
  //hier geht nur einmal write() !!
  
  Wire.write(values.asArray, sizeof(values));
}

Nun werde ich das ganze mit 2 Variablen versuchen und danach das ganze mit Kmh und Regenmenge:-)

Nun werde ich das ganze mit 2 Variablen versuchen

Mit zwei Variablen ist es das einfachste man verwendet ein anonymes struct in der Union. Das ist auch in dem Original-Beispiel so drin.

z.B. zwei ints:

union Data
{
  byte asArray[2 * sizeof(int)];
  struct
  {
     int var1;
     int var2;
   }
};

Das struct sorgt dafür dass die Speicheranordnung mit dem Array passt, aber da es keinen Namen hat kann man die Variablen wie vorher einfach über den Namen der Union ansprechen

Ich habe jetzt ein bisschen getestet sogar mit drei Variablen und komme nun mit der Sache klar.

Nun möchte ich den nächsten Schritt gehen und versuchen das ganze mit FHEM zu verbinden.

Hallo Zusammen,

ich habe nun versucht das Ganze in FHEM einzubinden, was auch erstmal geklappt hat, aaaaber ganz großes Problem habe ich nun mit der Zeit zwischen Daten Anfordern und Daten empfangen.

Zwischen den beiden Schritten muss eine Pause eingefügt werden. Ich habe dazu auch schon etwas gefunden weis aber nicht wie ich es richtig in die Configurable Firmata einbinden muss.

Ich hoffe mir Kann jemand von euch helfen.

Das V2.3 Protocol welches eingebunden werden muss:

I2C
/* I2C read/write request
 * -------------------------------
 * 0  START_SYSEX (0xF0) (MIDI System Exclusive)
 * 1  I2C_REQUEST (0x76)
 * 2  slave address (LSB)
 * 3  slave address (MSB) + read/write and address mode bits
      {7: always 0} + {6: reserved} + {5: address mode, 1 means 10-bit mode} +
      {4-3: read/write, 00 => write, 01 => read once, 10 => read continuously, 11 => stop reading} +
      {2-0: slave address MSB in 10-bit mode, not used in 7-bit mode}
 * 4  data 0 (LSB)
 * 5  data 0 (MSB)
 * 6  data 1 (LSB)
 * 7  data 1 (MSB)
 * ...
 * n  END_SYSEX (0xF7)
 */
/* I2C reply
 * -------------------------------
 * 0  START_SYSEX (0xF0) (MIDI System Exclusive)
 * 1  I2C_REPLY (0x77)
 * 2  slave address (LSB)
 * 3  slave address (MSB)
 * 4  register (LSB)
 * 5  register (MSB)
 * 6  data 0 LSB
 * 7  data 0 MSB
 * ...
 * n  END_SYSEX (0xF7)
 */
/* I2C config
 * -------------------------------
 * 0  START_SYSEX (0xF0) (MIDI System Exclusive)
 * 1  I2C_CONFIG (0x78)
 * 2  Delay in microseconds (LSB)
 * 3  Delay in microseconds (MSB)
 * ... user defined for special cases, etc
 * n  END_SYSEX (0xF7)
 */
Sampling Interval
The sampling interval sets how often analog data and i2c data is reported to the client. The default value is 19 milliseconds.
/* Set sampling interval
 * -------------------------------
 * 0  START_SYSEX (0xF0) (MIDI System Exclusive)
 * 1  SAMPLING_INTERVAL (0x7A)
 * 2  sampling interval on the millisecond time scale (LSB)
 * 3  sampling interval on the millisecond time scale (MSB)
 * 4  END_SYSEX (0xF7)
 */

MfG Mario

Und Noch die Configurable Firmata :

#include <Firmata.h>


//#include <SPI.h>
//#include <Ethernet.h>




#if defined ethernet_h || defined UIPETHERNET_H || defined _YUN_CLIENT_H_

#define NETWORK_FIRMATA
//replace with ip of server you want to connect to, comment out if using 'remote_host'
#define remote_ip IPAddress(192,168,0,1)
//replace with hostname of server you want to connect to, comment out if using 'remote_ip'
#define remote_host "server.local"
//replace with the port that your server is listening on
#define remote_port 3030
//replace with arduinos ip-address. Comment out if Ethernet-startup should use dhcp. Is ignored on Yun
#define local_ip IPAddress(192,168,0,6)
//replace with ethernet shield mac. It's mandatory every device is assigned a unique mac. Is ignored on Yun
const byte mac[] = {0x90, 0xA2, 0xDA, 0x0D, 0x07, 0x02};
#endif

// To configure, save this file to your working directory so you can edit it
// then comment out the include and declaration for any features that you do
// not need below.

// Also note that the current compile size for an Arduino Uno with all of the
// following features enabled is about 22.4k. If you are using an older Arduino
// or other microcontroller with less memory you will not be able to include
// all of the following feature classes.

#include <utility/DigitalInputFirmata.h>
DigitalInputFirmata digitalInput;

#include <utility/DigitalOutputFirmata.h>
DigitalOutputFirmata digitalOutput;

#include <utility/AnalogInputFirmata.h>
AnalogInputFirmata analogInput;

#include <utility/AnalogOutputFirmata.h>
AnalogOutputFirmata analogOutput;

#include <Servo.h> //wouldn't load from ServoFirmata.h in Arduino1.0.3
#include <utility/ServoFirmata.h>
ServoFirmata servo;

#include <Wire.h> //wouldn't load from I2CFirmata.h in Arduino1.0.3
#include <utility/I2CFirmata.h>
I2CFirmata i2c;

#include <utility/OneWireFirmata.h>
OneWireFirmata oneWire;

#include <utility/StepperFirmata.h>
StepperFirmata stepper;

#include <utility/FirmataExt.h>
FirmataExt firmataExt;

#include <utility/FirmataScheduler.h>
FirmataScheduler scheduler;

#include <utility/EncoderFirmata.h>
EncoderFirmata encoder;


// dependencies. Do not comment out the following lines
#if defined AnalogOutputFirmata_h || defined ServoFirmata_h
#include <utility/AnalogWrite.h>
#endif

#if defined AnalogInputFirmata_h || defined I2CFirmata_h || defined EncoderFirmata_h
#include <utility/FirmataReporting.h>
FirmataReporting reporting;
#endif

// dependencies for Network Firmata. Do not comment out.
#ifdef NETWORK_FIRMATA
#if defined remote_ip && defined remote_host
#error "cannot define both remote_ip and remote_host at the same time!"
#endif
#include <utility/EthernetClientStream.h>
#ifdef _YUN_CLIENT_H_
YunClient client;
#else
EthernetClient client;
#endif
#if defined remote_ip && !defined remote_host
#ifdef local_ip
EthernetClientStream stream(client, local_ip, remote_ip, NULL, remote_port);
#else
EthernetClientStream stream(client, IPAddress(0, 0, 0, 0), remote_ip, NULL, remote_port);
#endif
#endif
#if !defined remote_ip && defined remote_host
#ifdef local_ip
EthernetClientStream stream(client, local_ip, IPAddress(0, 0, 0, 0), remote_host, remote_port);
#else
EthernetClientStream stream(client, IPAddress(0, 0, 0, 0), IPAddress(0, 0, 0, 0), remote_host, remote_port);
#endif
#endif
#endif

void systemResetCallback()
{
  // initialize a defalt state

  // pins with analog capability default to analog input
  // otherwise, pins default to digital output
  for (byte i = 0; i < TOTAL_PINS; i++) {
    if (IS_PIN_ANALOG(i)) {
#ifdef AnalogInputFirmata_h
      // turns off pullup, configures everything
      Firmata.setPinMode(i, ANALOG);
#endif
    } else if (IS_PIN_DIGITAL(i)) {
#ifdef DigitalOutputFirmata_h
      // sets the output to 0, configures portConfigInputs
      Firmata.setPinMode(i, OUTPUT);
#endif
    }
  }

#ifdef FirmataExt_h
  firmataExt.reset();
#endif
}

void setup()
{
#ifdef NETWORK_FIRMATA
#ifdef _YUN_CLIENT_H_
  Bridge.begin();
#else
#ifdef local_ip
  Ethernet.begin((uint8_t *)mac, local_ip); //start ethernet
#else
  Ethernet.begin((uint8_t *)mac); //start ethernet using dhcp
#endif
#endif
  delay(1000);
#endif
  Firmata.setFirmwareVersion(FIRMATA_MAJOR_VERSION, FIRMATA_MINOR_VERSION);

#if defined AnalogOutputFirmata_h || defined ServoFirmata_h
  /* analogWriteCallback is declared in AnalogWrite.h */
  Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
#endif

#ifdef FirmataExt_h
#ifdef DigitalInputFirmata_h
  firmataExt.addFeature(digitalInput);
#endif
#ifdef DigitalOutputFirmata_h
  firmataExt.addFeature(digitalOutput);
#endif
#ifdef AnalogInputFirmata_h
  firmataExt.addFeature(analogInput);
#endif
#ifdef AnalogOutputFirmata_h
  firmataExt.addFeature(analogOutput);
#endif
#ifdef ServoFirmata_h
  firmataExt.addFeature(servo);
#endif
#ifdef I2CFirmata_h
  firmataExt.addFeature(i2c);
#endif
#ifdef OneWireFirmata_h
  firmataExt.addFeature(oneWire);
#endif
#ifdef StepperFirmata_h
  firmataExt.addFeature(stepper);
#endif
#ifdef FirmataReporting_h
  firmataExt.addFeature(reporting);
#endif
#ifdef FirmataScheduler_h
  firmataExt.addFeature(scheduler);
#endif
#ifdef EncoderFirmata_h
  firmataExt.addFeature(encoder);
#endif
#endif
  /* systemResetCallback is declared here (in ConfigurableFirmata.ino) */
  Firmata.attach(SYSTEM_RESET, systemResetCallback);

  // Network Firmata communicates with Ethernet-shields over SPI. Therefor all
  // SPI-pins must be set to IGNORE. Otherwise Firmata would break SPI-communication.
  // add Pin 10 and configure pin 53 as output if using a MEGA with Ethernetshield.
  // No need to ignore pin 10 on MEGA with ENC28J60, as here pin 53 should be connected to SS:
#ifdef NETWORK_FIRMATA
  // ignore SPI and pin 4 that is SS for SD-Card on Ethernet-shield
  for (byte i = 0; i < TOTAL_PINS; i++) {
    if (IS_PIN_SPI(i)
        || 4 == i
        // || 10==i //explicitly ignore pin 10 on MEGA as 53 is hardware-SS but Ethernet-shield uses pin 10 for SS
       ) {
      Firmata.setPinMode(i, IGNORE);
    }
  }
  //  pinMode(PIN_TO_DIGITAL(53), OUTPUT); configure hardware-SS as output on MEGA
  pinMode(PIN_TO_DIGITAL(4), OUTPUT); // switch off SD-card bypassing Firmata
  digitalWrite(PIN_TO_DIGITAL(4), HIGH); // SS is active low;

  // start up Network Firmata:
  Firmata.begin(stream);
#else
  // start up the default Firmata using Serial interface:
  Firmata.begin(57600);
#endif
  systemResetCallback();  // reset to default config
}

void loop()
{
#ifdef DigitalInputFirmata_h
  /* DIGITALREAD - as fast as possible, check for changes and output them to the
   * stream buffer using Firmata.write()  */
  digitalInput.report();
#endif

  /* STREAMREAD - processing incoming messagse as soon as possible, while still
   * checking digital inputs.  */
  while (Firmata.available()) {
    Firmata.processInput();
#ifdef FirmataScheduler_h
    if (!Firmata.isParsingMessage()) {
      goto runtasks;
    }
  }
  if (!Firmata.isParsingMessage()) {
runtasks: scheduler.runTasks();
#endif
  }

  /* SEND STREAM WRITE BUFFER - TO DO: make sure that the stream buffer doesn't go over
   * 60 bytes. use a timer to sending an event character every 4 ms to
   * trigger the buffer to dump. */

#ifdef FirmataReporting_h
  if (reporting.elapsed()) {
#ifdef AnalogInputFirmata_h
    /* ANALOGREAD - do all analogReads() at the configured sampling interval */
    analogInput.report();
#endif
#ifdef I2CFirmata_h
    // report i2c data for all device with read continuous mode enabled
    i2c.report();
#endif
#ifdef EncoderFirmata_h
    // report encoders positions if reporting enabled.
    encoder.report();
#endif
  }
#endif
#ifdef StepperFirmata_h
  stepper.update();
#endif
#if defined NETWORK_FIRMATA && !defined local_ip &&!defined _YUN_CLIENT_H_
  if (Ethernet.maintain())
  {
    stream.maintain(Ethernet.localIP());
  }
#endif
}