Trage IR Remote

Ik heb alleen een Uno met een 16x2 display. Maar het onderstaande stukje in setup() prints zoals ik verwacht

  lcd.begin(16, 2);  // <=== aangepast voor mijn scherm

  printUserInfo();

  lcd.clear();

  lcd.print("Trappe");
  lcd.setCursor(7, 0);
  lcd.print(" Av");

Er is een kans dat je de lcd.clear() over het hoofd hebt gezien die achter de printUserInfo() staat. Dus als je jouw stukje code tussen printUserInfo() en lcd.clear() plaats, wordt het onmiddelijk weer gewist.

Anders moet je je setup() even hier plaatsen zodat ik kan kijken.

Ik heb gisteren vergeten te vertellen hoe je de velden van een struct kunt gebruiken. In de meeste gevallen is dat met een punt (.).

pinMode(irLUT[cnt].pinLed, OUTPUT);
                  ^
                  |

Je zult soms ook de constructie -> zien; dat wordt gebruikt als je variabele een zogenaamde pointer is.

// Edit: missing printUserInfo() function added.

En dit is deel twee.

Je bent nu hopelijk een klein beetje bekend met structs.

Voor alle ingangen die je in de gaten houdt heb je een titel die je op een bepaalde plek (y/x) wilt tonen op de LCD en een status die je op een andere plek (y/x) wilt tonen. De definitie van de struct ziet er als volgt uit

/*
  LCDDATA combines information for the display
  This is a helper that is used in the LIGHTSTATUS and OTHERSTATUS structs
*/
struct LCDDATA
{
  // title and title position
  const char *title;
  const byte titleY;
  const byte titleX;
  // state and state position
  const char *txtActive;
  const char *txtInactive;
  const byte stateY;
  const byte stateX;
  // symbol index
  const byte symbol;
};

Een typisch voorbeeld voor een initialisatie van een LCDDATA is bv

{"Trappe",    0, 0, "P",   "Av",   8, 0, 8}
  ^           ^  ^   ^      ^      ^  ^  ^
  |           |  |   |      |      |  |  |
  |           |  |   |      |      |  |  +-- index van symbool
  |           |  |   |      |      |  +----- x positie voor de status
  |           |  |   |      |      +-------- y positie voor de status  
  |           |  |   |      +--------------- inactieve status
  |           |  |   +---------------------- actieve status
  |           |  +-------------------------- x positie titel
  |           +----------------------------- y positie titel
  +----------------------------------------- titel

symbol waarde 255 (0xFF) is gebruikt als een uizondering; als de waarde 255 is zal er geen symbool worden geplaatst. We kunnen nu een functie schrijven die de titels op de juist plek op het scherm zet en een functie die de status voor iedere ingang op het scherm zet.

/*
  show the title associated with a sense input on the lcd
  In:
    (title) text to display
*/
void showSenseTitle(const LCDDATA &text)
{
  lcd.setCursor(text.titleY, text.titleX);
  lcd.print(text.title);
}

Deze functie heeft een argument, een referentie (aangegeven met de &) naar een LCDDATA struct. Het zet de lcd cursor op de gespecificeerde titel plek en print vervolgens de titel.

De functie die de status print is praktisch hetzelfde maar met twee argumenten.

/*
  show the state of the input on the lcd
  In:
    the relevant section that needs to be updated
    the state of the sense pin
*/
void showSenseState(const LCDDATA &text, int state)
{
  lcd.setCursor(text.stateY, text.stateX);
  if (state == LOW)
  {
    lcd.print(text.txtInactive);
  }
  else
  {
    lcd.print(text.txtActive);
    if (text.symbol != 255)
    {
      lcd.write((byte)text.symbol);
    }
  }
}

Omdat digitalRead() een int teruggeeft, is het tweede argument van het type int. Eerst wordt de cursor weer op de juiste plek gezet en vervolgens wordt, afhankelijk van de status, de tekst en eventueel het symbool geprint.

Nu definieren we ook een struct for de ingangs signalen. Om het iets simpeler te houden gebruik ik tweede veschillende structs, een voor de lichten (een (1) led als indicatie) en een voor de garage deur en de dieren in de tuin (2 of 3 leds).

De struct voor de lichten heeft een pin die in de gaten gehouden wordt (je originele inputPinX), een pin waar de indicatie led op is aangesloten (je originele outputPinX), informatie voor de LCD (in de vorm van LCD data) en een variabele waarin je de laatste status kunt opslaan (niet gebruikt maar handig om te hebben als je wilt reageren op de verandering van de status inplaats van op de status).

/*
  LIGHTSTATUS defines the relationship between an input (sense) pin, the led indicator pin and the LCD text
*/
struct LIGHTSTATUS
{
  // pins associated with light status
  const byte pinSense;      // the pin that senses the status
  const byte pinIndicator;  // the pin that controls the indicator LED
  const LCDDATA lcdText;    // text to display
  byte previousStatus;      // previous status of the pin
};

pinSense is de vervanger voor inputPinX, pinIndicator is de vervanger voor outputPinX.

We kunnen nu een array van LIGHTSTATUS struct definieren met all informatie die bij elkaar hoort

/*
  The different lights that are monitored
*/
LIGHTSTATUS lightStatus[] =
{
  {23, 22, {"Trappe",    0, 0, "P",   "Av",   8, 0, 8}, LOW},
  {25, 24, {"Garage",   11, 0, "P",   "Av",  18, 0, 8}, LOW},
  {27, 26, {"L.Hal",     0, 1, "P",   "Av",   8, 1, 8}, LOW},
  {29, 28, {"S.Hal",    11, 1, "P",   "Av",  18, 1, 8}, LOW},
  {31, 30, {"Korr",      0, 2, "P",   "Av",   8, 2, 0}, LOW},
  {33, 32, {"Vasker",   11, 2, "P",   "Av",  18, 2, 8}, LOW},
};
  {23, 22, {"Trappe",    0, 0, "P",   "Av",   8, 0, 8}, LOW},
  ^^   ^   ^ ^           ^  ^   ^      ^      ^  ^  ^^     ^
  ||   |   | |           |  |   |      |      |  |  ||     |
  ||   |   | |           |  |   |      |      |  |  ||     +-- eind van array element
  ||   |   | |           |  |   |      |      |  |  |+-------- eind van de LCDDATA
  ||   |   | |           |  |   |      |      |  |  +--------- symbool dat gebruikt moet worden
  ||   |   | |           |  |   |      |      |  +------------ x positie voor status
  ||   |   | |           |  |   |      |      +--------------- y positie voor status
  ||   |   | |           |  |   |      +---------------------- de status text als de pin niet actief is
  ||   |   | |           |  |   +----------------------------- de status text als de pin actief is
  ||   |   | |           |  +--------------------------------- x positie voor de titel 
  ||   |   | |           +------------------------------------ y positie voor de titel
  ||   |     +------------------------------------------------ de titel van wat in de gaten wordt gehouden
  ||   +------------------------------------------------------ begin van de LCDDATA
  ||   +------------------------------------------------------ de pin voor de indicator
  |+---------------------------------------------------------- de pin voor de ingang
  +----------------------------------------------------------- begin van array element

Nu kun je in setup() weer door alle elementen itereren en de pinnen ingang of uitgang maken en je kunt nu ook de teksten op de LCD setten

void setup()
{
  ...
  ...

  // set up IO pins and show the lcd text
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(lightStatus); cnt++)
  {
    pinMode(lightStatus[cnt].pinSense, INPUT);
    pinMode(lightStatus[cnt].pinIndicator, OUTPUT);
    showSenseTitle(lightStatus[cnt].lcdText);
    showSenseState(lightStatus[cnt].lcdText, LOW);
  }
  ...
  ...
}

En als laatse kun je de ingangen in de gaten houden en op de lcd en leds de status laten zien in de *monitor()* functie
```c++
/*
  monitor sense inputs and indicate on the lcd and leds
*/
void monitor()
{
  // check the light sense inputs and take action
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(lightStatus); cnt++)
  {
    if (digitalRead(lightStatus[cnt].pinSense) == HIGH)
    {
      digitalWrite(lightStatus[cnt].pinIndicator, HIGH);
      showSenseState(lightStatus[cnt].lcdText, HIGH);
    }
    else
    {
      digitalWrite(lightStatus[cnt].pinIndicator, LOW);
      showSenseState(lightStatus[cnt].lcdText, LOW);
    }
    lightStatus[cnt].previousStatus = digitalRead(lightStatus[cnt].pinSense);
  }

  // check the other sense inputs (gagage door and animal)
  // todo
}

De volledige code tot nu toe (garage deur en beestenboel zit hier nog niet in).

// macro to calculate number of elements in any array (char, int, struct etc.)
#define NUMELEMENTS(x) (sizeof(x)/sizeof(x[0]))

#include <IRremote.h>
#include <LiquidCrystal.h>
// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 7, en = 6, d4 = 5, d5 = 4, d6 = 3, d7 = 2;

LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
byte SMILEY[8] = {
  B00100,
  B00000,
  B11111,
  B00001,
  B11111,
  B10001,
  B11111,
};

/*
  LCDDATA combines information for the display
  This is a helper that is used in the LIGHTSTATUS and OTHERSTATUS structs
*/
struct LCDDATA
{
  // title and title position
  const char *title;
  const byte titleY;
  const byte titleX;
  // state and state position
  const char *txtActive;
  const char *txtInactive;
  const byte stateY;
  const byte stateX;
  // symbol index
  const byte symbol;
};

/*
  LIGHTSTATUS defines the relationship between an input (sense) pin, the led indicator pin and the LCD text
*/
struct LIGHTSTATUS
{
  // pins associated with light status
  const byte pinSense;      // the pin that senses the status
  const byte pinIndicator;  // the pin that controls the indicator LED
  const LCDDATA lcdText;    // text to display
  byte previousStatus;      // previous status of the pin
};

/*
  The different lights that are monitored
*/
LIGHTSTATUS lightStatus[] =
{
  {23, 22, {"Trappe",    0, 0, "P",   "Av",   8, 0, 8}, LOW},
  {25, 24, {"Garage",   11, 0, "P",   "Av",  18, 0, 8}, LOW},
  {27, 26, {"L.Hal",     0, 1, "P",   "Av",   8, 1, 8}, LOW},
  {29, 28, {"S.Hal",    11, 1, "P",   "Av",  18, 1, 8}, LOW},
  {31, 30, {"Korr",      0, 2, "P",   "Av",   8, 2, 0}, LOW},
  {33, 32, {"Vasker",   11, 2, "P",   "Av",  18, 2, 8}, LOW},
};

struct OUTPUTCONTROL
{
  const uint32_t code;
  const byte pinLed;
};

OUTPUTCONTROL irLUT[] =
{
  {0x00FF30CF, A1},
  {0x00FF18E7, A2},
  {0x00FF7A85, A3},
  {0x00FF10EF, A4},
  {0x00FF38C7, A5},
  {0x00FF5AA5, A6},
  {0x00FF42BD, A7},
  {0x00FF4AB5, A8},
};


const byte RECV_PIN = A0;
const byte pinIRindicator = LED_BUILTIN;  // was pin 13; don't use magic numbers

// variables will change:
IRrecv irrecv(RECV_PIN);
decode_results results;

// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
//  decode_results *results = (decode_results *)v
void dump(decode_results *results) {
}

void setup()
{
  // because we might immediately want to use serial, I've made this the first line
  Serial.begin(9600);

  // IR pin
  pinMode(RECV_PIN, INPUT);
  // IR indicator led
  pinMode(pinIRindicator, OUTPUT);
  // start the receiver
  irrecv.enableIRIn();  


  // set up the LCD's number of columns and rows:
  lcd.begin(20, 4);
  printUserInfo();
  lcd.clear();

  // set all led pins that are controlled by the IR as output
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(irLUT); cnt++)
  {
    pinMode(irLUT[cnt].pinLed, OUTPUT);
  }

  // set up IO pins and show the lcd text
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(lightStatus); cnt++)
  {
    pinMode(lightStatus[cnt].pinSense, INPUT);
    pinMode(lightStatus[cnt].pinIndicator, OUTPUT);
    showSenseTitle(lightStatus[cnt].lcdText);
    showSenseState(lightStatus[cnt].lcdText, LOW);
  }
}


void loop()
{
  controlOutputs();
  monitor();
}

/*
  monitor sense inputs and indicate on the lcd and leds
*/
void monitor()
{
  // check the light sense inputs and take action
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(lightStatus); cnt++)
  {
    if (digitalRead(lightStatus[cnt].pinSense) == HIGH)
    {
      digitalWrite(lightStatus[cnt].pinIndicator, HIGH);
      showSenseState(lightStatus[cnt].lcdText, HIGH);
    }
    else
    {
      digitalWrite(lightStatus[cnt].pinIndicator, LOW);
      showSenseState(lightStatus[cnt].lcdText, LOW);
    }
    lightStatus[cnt].previousStatus = digitalRead(lightStatus[cnt].pinSense);
  }

  // check the other sense inputs (gagage door and animal)
  // todo
}

/*
  show the title associated with a sense input on the lcd
  In:
    (title) text to display
*/
void showSenseTitle(const LCDDATA &text)
{
  lcd.setCursor(text.titleY, text.titleX);
  lcd.print(text.title);
}

/*
  show the state of the input on the lcd
  In:
    the relevant section that needs to be updated
    the state of the sense pin
*/
void showSenseState(const LCDDATA &text, int state)
{
  lcd.setCursor(text.stateY, text.stateX);
  if (state == LOW)
  {
    lcd.print(text.txtInactive);
  }
  else
  {
    lcd.print(text.txtActive);
    if (text.symbol != 255)
    {
      lcd.write((byte)text.symbol);
    }
  }
}

/*
  control the output pins based on received IR code
*/
void controlOutputs()
{
  static int on = LOW;
  static uint32_t last = millis();


  if (irrecv.decode(&results))
  {
    // If it's been at least 1/4 second since the last
    // IR received, toggle the relay
    if (millis() - last > 250)
    {
      on = !on;
      digitalWrite(pinIRindicator, on ? HIGH : LOW);
      dump(&results);
    }

    // find the IR code and pulse the led pin
    for (uint8_t cnt = 0; cnt < NUMELEMENTS(irLUT); cnt++)
    {
      // if the received IR code matches
      if (results.value == irLUT[cnt].code)
      {
        // pulse the pin
        digitalWrite(irLUT[cnt].pinLed, HIGH);
        delay(50);
        digitalWrite(irLUT[cnt].pinLed, LOW);
      }
    }
    last = millis();
    irrecv.resume(); // Receive the next value
  }
}

/*
  print some user information
*/
void printUserInfo()
{
  lcd.print("Riti & Jan Pronk");
  delay(1000);
  lcd.setCursor(0, 1);
  lcd.print("Hedalsvegen 2832");
  delay(1000);
  lcd.setCursor(0, 2);
  lcd.print("3528 Hedalen");
  delay(1000);
  lcd.setCursor(0, 3);
  lcd.print("+47 46552668");
  delay(1000);
}

Je globale variabelen zijn een beetje verplaatstst. Ik heb ook pin 13 een (logische) naam gegeven. Het is niet verstanding om magische nummers te gebruiken; als je ooit een andere pin wilt gebruiken moet je het op verschillende plaatsen aanpassen (en als je eer eentje vergeet krijg je mogelijk ongewenste resultaten en zit je een uur of meer te puzzelen waarom het niet werkt).

Misschien morgen, anders in het weekend, het laatste deel voor de garage deur en de beestenboel.

ik zal morgen eerst eens beginnen met het uitprinten van alles hierboven, dat leest een beetje makkelijker, en kan ik het beter met elkaar vergelijken, hier op het scherm, duizeld het mij nu een beetje, ook zal ik kijken waar ik n cursus C kan vinden, ivm het programmeren.

iig heel hartelijk bedankt voor alle tijd, die je er tot nu toe hebt ingestoken

Arduino: 1.8.13 (Windows Store 1.8.42.0) (Windows 10), Board: "Arduino Mega or Mega 2560, ATmega2560 (Mega 2560)"

T:\ARDUINO\STERRETJE001\STERRETJE001.ino: In function 'void setup()':

STERRETJE001:114:3: error: 'printUserInfo' was not declared in this scope

printUserInfo();

^~~~~~~~~~~~~

Multiple libraries were found for "LiquidCrystal.h"

Used: T:\ARDUINO\libraries\LiquidCrystal

Not used: C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\LiquidCrystal

exit status 1

'printUserInfo' was not declared in this scope

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

OOPS, die moet eruit gevallen zijn tijdens het kopieren voor het antwoord :frowning: En niet gecompileerd voordat ik het erin plakte :cry: Ik heb het programma hierboven aangepast. Er was geen verandering in die functie, je had hem kunnen copieren van het programma van gisteren :wink:

kan jij mij uitleggen waar om dit bij mij
dit op mijn lcd geeft?

B11111,
B00000,
B11111,
B00000,
B11111,
B00000,
B11111,

Geen idee. Maar je moet het karakter creeren voordat je lcd.begin() aanroept. Zie LiquidCrystal - Arduino Reference.

En dan het gedeelte om de andere ingangen in de gaten te houden.

Hoewel een aangepaste LIGHTSTATUS hiervoor gebruikt had kunnen worden, heb ik gezien je kennis niveau besloten hier een andere struct te gebruiken. Het probleem is dat hier meerdere uitgangs pinnen gebruikt worden en dat sommige de omgekeerde waarde van de ingang weergeven.

Om hier mee overweg te kunnen, is er een 'helper struct gebruikt die de indicatie pin gaat vervangen. Zoals je misschien hebt gezien, volgt de indicatie led voor de lichten de ingangs pin.

/*
  INDICATORCONTROL defines the relationship between an indicator pin and the output level
  This is a helper that is used in the OTHERSTATUS struct
*/
struct INDICATORCONTROL
{
  const byte pinIndicator;  // the pin that controls the indicator LED
  const bool invert;        // output level is inverse of input level if set to true
};

Deze struct bevat de indicatie pin en geeft aan of de pin die ingang moet volgen of omgekeerd moet worden. Op die manier kun je schakelen tussen twee leds als je het goed aanpakt.

De struct voor de status van de garage deur en de beestenboel is een variatie op LIGHTSTATUS

/*
  OTHERSTATUS defines the relationship between an input (sense) pin, the led indicator pins and the LCD text
*/
struct OTHERSTATUS
{
  const byte pinSense;
  const INDICATORCONTROL indicators[3];
  const LCDDATA lcdText;
  byte previousStatus;
};

Zoals je kunt zien, is de indicatie pin vervangen door een INDICATORCONTROL. De 3 in indicators[3] geeft aan dat je maximaal drie indicator pinnen kunt hebben; je kunt dit aanpassen aan je wensen (misschien heb je er maar twee nodig maar je originele programma bestuurde 3 pinnen). De initialisatie gebaseerd op je originele programma.

/*
  The different 'others' that are monitored
*/
OTHERSTATUS otherStatus[] =
{
  {35, {{34, false}, {44, false}, {42, true}}, {"Garagep.",  0, 3, "Opp", "Ned",  8, 3, 255}, LOW},
  {37, {{36, false}},                          {"DYR",      11, 3, "Ja",  "Nei", 17, 8, 255}, LOW},
};

Voor de garage deur zijn er drie indicatie pinnen, voor de beestenboel slechts een (1) omdat ik geen andere pinnen kon vinden in je originele programma.

  {35, {  {  34, false}, {  44, false}, {  42, true}  }, ...
       ^  ^  ^   ^    ^  ^  ^   ^    ^  ^  ^   ^   ^  ^
       |  |  |   |    |  |  |   |    |  |  |   |   |  |
       |  |  |   |    |  |  |   |    |  |  |   |   |  +-- einde van INDICATORCONTROL array
       |  |  |   |    |  |  |   |    |  |  |   |   +----- einde van derde element van indicator array
       |  |  |   |    |  |  |   |    |  |  |   +--------- geeft and dat uitgang omgekeerde waarde heeft van ingang
       |  |  |   |    |  |  |   |    |  |  +------------- indicatie pin
       |  |  |   |    |  |  |   |    |  +---------------- begin van derde element van indicator array
       |  |  |   |    |  |  |   |    +------------------- einde van tweede element van indicator array
       |  |  |   |    |  |  |   +------------------------ geeft and dat uitgang dezelfde waarde heeft als ingang
       |  |  |   |    |  |  +---------------------------- indicatie pin
       |  |  |   |    |  +------------------------------- begin van tweede element van indicator array
       |  |  |   |    +---------------------------------- einde van eerste element van indicator array
       |  |  |   +--------------------------------------- geeft and dat uitgang dezelfde waarde heeft als ingang
       |  |  +------------------------------------------- indicatie pin
       |  +---------------------------------------------- begin van eerste elemenet van indicator array
       +------------------------------------------------- begin van INDICATORCONTROL array

Zoals gezegd, voor de beestenboel is er slechts een (1) element; de andere twee zijn automatisch (0, false} als otherStatus een globaal array is zoals in dit programma; anders zul je dat zelf moeten invullen. Wees je ervan bewust dat 0 in principe een geldig pin nummer is maar omdat pin 0 op de Mega the RX ingang is en we de seriele poort gebruiken kunnen we pin nummer 0 als een indicatie gebruiken dat de pin overgeslagen moet worden bij de initialisatie. Je moet zelf even de indicators van de beestenboel aanvullen.

Zoals we al eerder hebben gedaan voor de LIGHTSTATUS, kunnen we nu de pinnen als ingang an uitgang configureren en gegevens op de LCD zetten. Misschien belangrijk om te noemen is het gebruik van een for-loop binnen een for-loop; the buitenste for-loop loopt door de OTHERSTATUS elementen en de binnenste for-loop loopt door de INDICATORCONTROL elementen in een OTHERSTATUS element.

  // set up IO pins and show the lcd text
  for (uint8_t statusCnt = 0; statusCnt < NUMELEMENTS(otherStatus); statusCnt++)
  {
    pinMode(otherStatus[statusCnt].pinSense, INPUT);
    // set up IO pins and show the lcd text
    for (uint8_t indicatorCnt = 0; indicatorCnt < NUMELEMENTS(otherStatus[statusCnt].indicators); indicatorCnt++)
    {
      // if a valid indicator pin is specified
      if (otherStatus[statusCnt].indicators[indicatorCnt].pinIndicator != 0)
      {
        pinMode(otherStatus[statusCnt].indicators[indicatorCnt].pinIndicator, OUTPUT);
      }
    }
    showSenseTitle(otherStatus[statusCnt].lcdText);
    showSenseState(otherStatus[statusCnt].lcdText, LOW);
  }

Als laatste stap kunnen we nu de monitor() functie verder invullen zodat de garage deur en de beestenboel in de gaten gehouden kunnen worden.

  // check the other sense inputs (gagage door and animal)
  for (uint8_t statusCnt = 0; statusCnt < NUMELEMENTS(otherStatus); statusCnt++)
  {
    // get the status of the sense pin
    int status = digitalRead(otherStatus[statusCnt].pinSense);
    // and show it on the LCD
    showSenseState(otherStatus[statusCnt].lcdText, status);
    // loop through the indicators
    for (uint8_t indicatorCnt = 0; indicatorCnt < NUMELEMENTS(otherStatus[statusCnt].indicators); indicatorCnt++)
    {
      if (otherStatus[statusCnt].indicators[indicatorCnt].invert == false)
      {
        digitalWrite(otherStatus[statusCnt].indicators[indicatorCnt].pinIndicator, status);
      }
      else
      {
        digitalWrite(otherStatus[statusCnt].indicators[indicatorCnt].pinIndicator, !status);
      }
    }
    // update the previous status
    otherStatus[statusCnt].previousStatus = status;
  }

Hieronder het volledige programma, het kan nog enigzins verbeterd worden (bv. alle definities en constanten kunnen in een aparte file worden geplaatst) maar voor nu volstaat het. Bestudeer het, begrijp het, test het. Laat me weten of je dingen niet begrijpt en of zaken niet werken zoals je verwacht.

// macro to calculate number of elements in any array (char, int, struct etc.)
#define NUMELEMENTS(x) (sizeof(x)/sizeof(x[0]))

#include <IRremote.h>
#include <LiquidCrystal.h>

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 7, en = 6, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

byte SMILEY[8] = {
  B00100,
  B00000,
  B11111,
  B00001,
  B11111,
  B10001,
  B11111,
};

/*
  INDICATORCONTROL defines the relationship between an indicator pin and the output level
  This is a helper that is used in the OTHERSTATUS struct
*/
struct INDICATORCONTROL
{
  const byte pinIndicator;  // the pin that controls the indicator LED
  const bool invert;        // output level is inverse of input level if set to true
};

/*
  LCDDATA combines information for the display
  This is a helper that is used in the LIGHTSTATUS and OTHERSTATUS structs
*/
struct LCDDATA
{
  // title and title position
  const char *title;
  const byte titleY;
  const byte titleX;
  // state and state position
  const char *txtActive;
  const char *txtInactive;
  const byte stateY;
  const byte stateX;
  // symbol index
  const byte symbol;
};

/*
  LIGHTSTATUS defines the relationship between an input (sense) pin, the led indicator pin and the LCD text
*/
struct LIGHTSTATUS
{
  // pins associated with light status
  const byte pinSense;      // the pin that senses the status
  const byte pinIndicator;  // the pin that controls the indicator LED
  const LCDDATA lcdText;    // text to display
  byte previousStatus;      // previous status of the pin
};

/*
  The different lights that are monitored
*/
LIGHTSTATUS lightStatus[] =
{
  {23, 22, {"Trappe",    0, 0, "P",   "Av",   8, 0, 8}, LOW},
  {25, 24, {"Garage",   11, 0, "P",   "Av",  18, 0, 8}, LOW},
  {27, 26, {"L.Hal",     0, 1, "P",   "Av",   8, 1, 8}, LOW},
  {29, 28, {"S.Hal",    11, 1, "P",   "Av",  18, 1, 8}, LOW},
  {31, 30, {"Korr",      0, 2, "P",   "Av",   8, 2, 0}, LOW},
  {33, 32, {"Vasker",   11, 2, "P",   "Av",  18, 2, 8}, LOW},
};

/*
  OTHERSTATUS defines the relationship between an input (sense) pin, the led indicator pins and the LCD text
*/
struct OTHERSTATUS
{
  const byte pinSense;
  const INDICATORCONTROL indicators[3];
  const LCDDATA lcdText;
  byte previousStatus;
};

/*
  The different 'others' that are monitored
*/
OTHERSTATUS otherStatus[] =
{
  {35, {{34, false}, {44, false}, {42, true}}, {"Garagep.",  0, 3, "Opp", "Ned",  8, 3, 255}, LOW},
  {37, {{36, false}},                          {"DYR",      11, 3, "Ja",  "Nei", 17, 8, 255}, LOW},
};

/*
  struct with relationship between IR code and output pin
*/
struct OUTPUTCONTROL
{
  const uint32_t code;
  const byte pinLed;
};

/*
  Lookup table to associate remote control buttons with pins that need to be controlled
*/
OUTPUTCONTROL irLUT[] =
{
  {0x00FF30CF, A1},
  {0x00FF18E7, A2},
  {0x00FF7A85, A3},
  {0x00FF10EF, A4},
  {0x00FF38C7, A5},
  {0x00FF5AA5, A6},
  {0x00FF42BD, A7},
  {0x00FF4AB5, A8},
};

const byte RECV_PIN = A0;
const byte pinIRindicator = LED_BUILTIN;  // was pin 13; don't use magic numbers

// variables will change:
IRrecv irrecv(RECV_PIN);
decode_results results;

// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
//  decode_results *results = (decode_results *)v
void dump(decode_results *results) {
}

void setup()
{
  // because we might immediately want to use serial, I've made this the first line
  Serial.begin(9600);

  // IR releated
  pinMode(RECV_PIN, INPUT);
  irrecv.enableIRIn(); // Start the receiver
  pinMode(pinIRindicator, OUTPUT);

  // set all led pins that are controlled by the IR as output
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(irLUT); cnt++)
  {
    pinMode(irLUT[cnt].pinLed, OUTPUT);
  }

  // set up IO pins and show the lcd text
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(lightStatus); cnt++)
  {
    pinMode(lightStatus[cnt].pinSense, INPUT);
    pinMode(lightStatus[cnt].pinIndicator, OUTPUT);
    showSenseTitle(lightStatus[cnt].lcdText);
    showSenseState(lightStatus[cnt].lcdText, LOW);
  }

  // set up IO pins and show the lcd text
  for (uint8_t statusCnt = 0; statusCnt < NUMELEMENTS(otherStatus); statusCnt++)
  {
    pinMode(otherStatus[statusCnt].pinSense, INPUT);
    // set up IO pins and show the lcd text
    for (uint8_t indicatorCnt = 0; indicatorCnt < NUMELEMENTS(otherStatus[statusCnt].indicators); indicatorCnt++)
    {
      // if a valid indicator pin is specified
      if (otherStatus[statusCnt].indicators[indicatorCnt].pinIndicator != 0)
      {
        pinMode(otherStatus[statusCnt].indicators[indicatorCnt].pinIndicator, OUTPUT);
      }
    }
    showSenseTitle(otherStatus[statusCnt].lcdText);
    showSenseState(otherStatus[statusCnt].lcdText, LOW);
  }

  // create custom character
  lcd.createChar(0, SMILEY);
  // set up the LCD's number of columns and rows
  lcd.begin(20, 4);

  // print some user info
  printUserInfo();
  // and clear the LCD for the more serious work
  lcd.clear();
}

void loop()
{
  controlOutputs();
  monitor();
}

/*
  print some user information
*/
void printUserInfo()
{
  lcd.print("Riti & Jan Pronk");
  delay(1000);
  lcd.setCursor(0, 1);
  lcd.print("Hedalsvegen 2832");
  delay(1000);
  lcd.setCursor(0, 2);
  lcd.print("3528 Hedalen");
  delay(1000);
  lcd.setCursor(0, 3);
  lcd.print("+47 46552668");
  delay(1000);
}

/*
  monitor sense inputs and indicate on the lcd and leds
*/
void monitor()
{
  // check the light sense inputs and take action
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(lightStatus); cnt++)
  {
    if (digitalRead(lightStatus[cnt].pinSense) == HIGH)
    {
      digitalWrite(lightStatus[cnt].pinIndicator, HIGH);
      showSenseState(lightStatus[cnt].lcdText, HIGH);
    }
    else
    {
      digitalWrite(lightStatus[cnt].pinIndicator, LOW);
      showSenseState(lightStatus[cnt].lcdText, LOW);
    }
    lightStatus[cnt].previousStatus = digitalRead(lightStatus[cnt].pinSense);
  }

  // check the other sense inputs (gagage door and animal)
  for (uint8_t statusCnt = 0; statusCnt < NUMELEMENTS(otherStatus); statusCnt++)
  {
    // get the status of the sense pin
    int status = digitalRead(otherStatus[statusCnt].pinSense);
    // and show it on the LCD
    showSenseState(otherStatus[statusCnt].lcdText, status);
    // loop through the indicators
    for (uint8_t indicatorCnt = 0; indicatorCnt < NUMELEMENTS(otherStatus[statusCnt].indicators); indicatorCnt++)
    {
      if (otherStatus[statusCnt].indicators[indicatorCnt].invert == false)
      {
        digitalWrite(otherStatus[statusCnt].indicators[indicatorCnt].pinIndicator, status);
      }
      else
      {
        digitalWrite(otherStatus[statusCnt].indicators[indicatorCnt].pinIndicator, !status);
      }
    }
    // update the previous status
    otherStatus[statusCnt].previousStatus = status;
  }
}

/*
  show the title associated with a sense input on the lcd
  In:
    (title) text to display
*/
void showSenseTitle(const LCDDATA &text)
{
  lcd.setCursor(text.titleY, text.titleX);
  lcd.print(text.title);
}

/*
  show the state of the input on the lcd
  In:
    the relevant section that needs to be updated
    the state of the sense pin
*/
void showSenseState(const LCDDATA &text, int state)
{
  lcd.setCursor(text.stateY, text.stateX);
  if (state == LOW)
  {
    lcd.print(text.txtInactive);
  }
  else
  {
    lcd.print(text.txtActive);
    if (text.symbol != 255)
    {
      lcd.write((byte)text.symbol);
    }
  }
}

/*
  control the output pins based on received IR code
*/
void controlOutputs()
{
  static int on = LOW;
  static uint32_t last = millis();


  if (irrecv.decode(&results))
  {
    // If it's been at least 1/4 second since the last
    // IR received, toggle the relay
    if (millis() - last > 250)
    {
      on = !on;
      digitalWrite(pinIRindicator, on ? HIGH : LOW);
      dump(&results);
    }

    // find the IR code and pulse the led pin
    for (uint8_t cnt = 0; cnt < NUMELEMENTS(irLUT); cnt++)
    {
      // if the received IR code matches
      if (results.value == irLUT[cnt].code)
      {
        // pulse the pin
        digitalWrite(irLUT[cnt].pinLed, HIGH);
        delay(50);
        digitalWrite(irLUT[cnt].pinLed, LOW);
      }
    }
    last = millis();
    irrecv.resume(); // Receive the next value
  }
}

ziet er goed uit, maar ik zie nog enkele puntjes die niet helemaal kloppen, zal proberen die zelf uit te vinden.
OMG, ik hoop, dit ooit eens onder de knie (met prothese) te krijgen

IIG heel hartelijk bedankt, wat je allemaal voor mij hebt gedaan.

1 is opgelost

.. Verander het, en begrijp dan ook wat dat doet en waarom het dat doet..
Op die wijze ga je jezelf leren hoe een en ander werkt.
Maak heel kleine veranderingen en test die dan.
Ga niet van alles wijzigen, maar doorgrond het per wijziging, of draai die wijziging terug en probeer wat anders te doorgronden.

@sterretje en @MAS3 , ik zal het proberen, lukt het niet, dan durf ik het te vragen

Ik ben nieuwsgierig :wink:

@sterretje , de tekst: trappe, garage, l.hal, s.hal, korr, vasker, garagep, dyr staan niet meer op mn LCD
En ik heb een spatie moeten toevoegen, voor het woordje "ja" als er een dier in de tuin is, omdat anders de "i" van nei bleef staan

  // print some user info
  printUserInfo();
  // and clear the LCD for the more serious work
  lcd.clear();

Dit is op de verkeerde plek in mijn programma; probeer eens uit te vogelen waar het wel moet staan. Goede oefening :wink:

De problemen

  1. lcd.begin() is nog niet aangeroepen zodat de for-loops niks op het scherm 'kunnen' zetten.
  2. plek is verkeerd zodat, zelfs als de for-loops iets op het scherm zouden zetten, het wordt overschreven met je gebruikers info.
lcd.print("Trappe");
  lcd.setCursor(7, 0);
  lcd.print(" Av");
  //
  lcd.setCursor(11, 0);
  lcd.print("Garage");
  lcd.setCursor(18, 0);
  lcd.print("Av");
  //
  lcd.setCursor(0, 1);
  lcd.print("L.Hal");
  lcd.setCursor(8, 1);
  lcd.print("Av");
  //
  lcd.setCursor(11, 1);
  lcd.print("S.Hal");
  lcd.setCursor(18, 1);
  lcd.print("Av");
  //
  lcd.setCursor(0, 2);
  lcd.print("Korr");
  lcd.setCursor(8, 2);
  lcd.print("Av");
  //
  lcd.setCursor(11, 2);
  lcd.print("Vasker");
  lcd.setCursor(18, 2);
  lcd.print("Av");
  //
  lcd.setCursor(0, 3);
  lcd.print("Garagep.");
  lcd.setCursor(8, 3);
  lcd.print("Ned");
  //
  lcd.setCursor(13, 3);
  lcd.print("Dyr");
  lcd.setCursor(17, 3);
  lcd.print("Nei");
`
``
ik heb dit blokje achter de 
lcd.clear();
geplakt, dat lijkt mij goed te gaan

Dat was niet helemaal de bedoeling :wink: Mijn fout dat ik niet het volledige gedeelte heb gegeven dat verplaatst moest worden :frowning:

Dit moet je verplaatsen naar voor de eerste for-loop in setup()

  // create custom character
  lcd.createChar(0, SMILEY);
  // set up the LCD's number of columns and rows
  lcd.begin(20, 4);

  // print some user info
  printUserInfo();
  // and clear the LCD for the more serious work
  lcd.clear();

nog even 2 electronika vraagjes,
A: is het handig of beter om een input pin met een weerstand 1k naar gnd te leggen zodat de ingang niet zwevende is?

en
B: moet een output pin beveiligt worden met n diode, zodat er geen 5V naar toe kan lopen bij het parallel schakelen van 2 uitput pinnen?

Zolang je geen waarde hecht aan de toestand van de pin in je programma, maakt 't niet uit, als dat wel het geval is kan je ook de interne 'PULLUP' weerstand aan spreken dmv het definieren van de pin als 'INPUT_PULLUP"

je moet 2 output pinnen niet parallel schakelen. Wat zou de noodzaak zijn om dat te doen ?

je moet 2 output pinnen niet parallel schakelen. Wat zou de noodzaak zijn om dat te doen ?

1 is een outputpin, de andere is een draad die via een pushbutton ook een HIGH signaal geeft, beiden zouden via dezelfde draad een signaal geven om een poort van een andere chip te laten toggelen. daarom vroeg ik mij af, of het noodzakelijk is om de outputpin, met een diode, bv 1N4148 te "offen"

Ja, dat is noodzakelijk. Verder moet je checken wat de spec is van de andere kant (de PIC, vermoed ik). Die moet 5V minus de spanningsval over de diode nog als HOOG zien; waarschijnlijk ok.

Misschien eenvoudiger om de knoppen ook op je mega aan te sluiten en je programma aan te passen :wink: