Sketch via I2C met I/O expander

Hi forum leden. is al een tijdje geleden maar ben er nog :slight_smile:

na het een en ander te proberen de basis toch een beetje onder knie gekregen en heb mijn werkende sketch. nu wil ik deze sketch vermenigvuldigen en op een klein afstand van 3 meter zetten. de afstand is geen probleem maar zal dus niet genoeg poorten hebben. ik dacht hiervoor een pcf8575 I/O expander te gebruiken dat via I2c kan communiceren en dat wil me maar niet lukken. ook werken mijn motoren met puls commanden ( dus aan en uit in korte tijden). Weet ook niet of deze met in en output tegelijk te gebruiken is. of moet ik er specifiek een pcf voor de outputs en 1 voor de inputs gebruiken?
kan er iemand mij hierbij helpen ?

#include <math.h>
const int motor1R = 12; 
const int motor1L = 11; 
const int motor2R = 10; 
const int motor2L = 9;
const int motor3R = 8; 
const int motor3L = 7;
const int pomp = 4; //waterpomp
const int drukknoppin = 2;
const int gewensttemperatuur = 45;   //temperatur aan passen!!!!
const int laagdrempel = 30;
const int wachttijd = 50;  // wachttijd bij aan uit schakelen van spoelen!!
int temperatuur;
int temperatuurpin = A0;
int drukknop;
int A=0;
int AA=0;
int BB=0;
int CC=0;


void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(drukknoppin, INPUT_PULLUP);
pinMode(motor1R, OUTPUT);
pinMode(motor1L,OUTPUT);
pinMode(motor2R,OUTPUT);
pinMode(motor2L, OUTPUT);
pinMode(motor3R, OUTPUT);
pinMode(motor3L, OUTPUT);
pinMode(pomp, OUTPUT);
}

double Termistor(int analogOkuma){

 double temperatuur;
 temperatuur = log(((10240000 / analogOkuma) - 9850));
 temperatuur = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * temperatuur * temperatuur)) * temperatuur);
 temperatuur = temperatuur - 273.15;
 return temperatuur;
}

void loop() {
  // put your main code here, to run repeatedly:
  drukknop = digitalRead(drukknoppin);

    int deger = analogRead(A0);
  double temperatuur = Termistor(deger);

    Serial.print("knop: ");
  Serial.print(drukknop);
  Serial.println();
  Serial.print("tempertauur: ");
  Serial.print(temperatuur);
  Serial.print("°C");
  Serial.println();
  Serial.print("A=");
  Serial.print(A);
  Serial.println();
  Serial.print("AA=");
  Serial.print(AA);
  Serial.println();
  Serial.print("BB=");
  Serial.print(BB);
  Serial.println();
  Serial.print("CC=");
  Serial.print(CC);
  Serial.println();
  delay(500);



  if (drukknop == 0) { 
      A++;}
  
     if (A == 1 && temperatuur <= gewensttemperatuur && AA == 0) {
            digitalWrite(motor1R, LOW);
            digitalWrite(motor1L,HIGH);
            digitalWrite(motor2L, LOW);
            digitalWrite(motor2R,HIGH);
            digitalWrite(motor3R, LOW);
            digitalWrite(motor3L,HIGH);
            delay(wachttijd);
            digitalWrite(pomp, HIGH);
            digitalWrite(motor1L,LOW);
            digitalWrite(motor2R,LOW);
            digitalWrite(motor3L,LOW);    
            AA++; }

            if (A == 1 && AA == 1){ BB = 0;}

            
            
      if (A == 1 && temperatuur>=gewensttemperatuur && BB == 0) { 
            digitalWrite( pomp, LOW);
            digitalWrite( motor3L, LOW);
            digitalWrite( motor3R, HIGH);
            digitalWrite( motor1L, LOW);
            digitalWrite( motor1R, HIGH);
            digitalWrite( motor2R, LOW);
            digitalWrite( motor2L, HIGH);
            delay(wachttijd);
            digitalWrite( motor3R, LOW);
            digitalWrite( motor1R, LOW);
            digitalWrite( motor2L, LOW);
            BB++;
            }

            if (A == 1 && BB == 1){ AA = 0; CC = 0; A++;}
              

if (drukknop == 1 &&  A >= 2){
            A=0; AA=0; BB=0; CC=0;
            digitalWrite( pomp, LOW);
            digitalWrite( motor3L, LOW);
            digitalWrite( motor3R, HIGH);
            digitalWrite( motor1L, LOW);
            digitalWrite( motor1R, HIGH);
            digitalWrite( motor2R, LOW);
            digitalWrite( motor2L, HIGH);
            delay(wachttijd);
            digitalWrite( motor3R, LOW);
            digitalWrite( motor1R, LOW);
            digitalWrite(motor2L, LOW);
            }

            if (CC == 0  && temperatuur <= laagdrempel ) { 
            digitalWrite(motor1R, LOW);
            digitalWrite(motor1L,HIGH);
            delay(wachttijd);            
            digitalWrite(motor1R, LOW);
            digitalWrite(motor1L,LOW);            
            CC++;
             }            
            
}

de analoge ingang word dus niet vermenigvuldigd. die word later omgebouwd naar een digitale signaal.

mvg,
w-besp

Hoi.

Klein is een relatief begrip.
3 meter is voor i2c namelijk een enorme afstand, want i2c is nooit bedoeld voor zulke afstanden.
Het is echt bedoeld om te communiceren tussen chips op dezelfde print of opsteekprinten zoals Arduino de shields heeft.

Heb je geprobeerd te communiceren met korte verbindingen zoals een breadboardje direct naast je Arduino ?
Heb je daarbij ook de A0 - A2 pennen van de PCF aan GND gelegd om adressen 64 (0x40) (lezen) en 65 (0x41) (schrijven) in te stellen ?

Hi MAS3,

bedankt voor je duidelijke antwoord en de harde feit van I2C. of ik het geprobeerd heb op een korte afstand ? ja, met een UNO en een PCF8575 op een breadboard maar het lukte me niet zo direct. het programmeren lukte me ook nauwelijks. had hiervoor de library van Rob Tilaart gebruikt. kon het als output gebruiken maar tegelijkertijd niet als input op een ander pin. dus was gans het print ofwel output ofwel input, ook was de output wat aan de lage kant ( 3.1V) terwijl ik minstens 3.4V nodig heb om te kunnen schakelen via een L298N bordje. de motoren hebben een open spoel zoals een magneetvalve. ook de A0-A2 heb ik gesoldeerd met de GND en had de adres 0X20 hiervoor.

voor een latere uitbereiding of een andere project zou ik op 10 meter moeten kunnen communiceren tussen de UNO/Nano en een expander. is dit dat op een of andere manier niet mogelijk ? de spanning kan ik wat hoger krijgen voor zulke afstand door het te regelen via een dc to dc converter en eventueel een weerstand plaatsen om overspanning te voorkomen. hoe kan me dat lukken ?

een vraagje:
hoe werken de paralafonies aan de deuren dan met lange afstanden ?
of hoe werken de maschines in fabrieken op zulke afstanden? heb hiervan niet zo direct inzicht en dus begrijp ik het niet zo op 123.

Er zijn I2C extender chips; je hebt er waarschijnlijk een paar nodig.

Waarschijnlijk seriele communicatie via RS232 / RS422 / RS485.

Hi sterretje,

Hoe bedoel je met een paar I2C extenders? Bedoel je de TCA chips?

seriele communicatie via RS232 / RS422 / RS485. Hoe werken deze dan? Heb zo wat in de rapte gaan zien en blijkbaar zou dit dan via bytes werken door 1 en 0 te schrijven wat voor mij weer onbekende gronden zijn.

Om mijn doel duidelijk te schetsen:
Ik wil de bovenstaande sketch op 2 a 3 plaatsen willen gebruiken met wat afstand tussen.
Dus 1 centrale uno, en op 2 plaatsen apart dezelfde sketch gebruiken die elks een L298N bedienen (wel met verschillende benoemingen en adressen natuurlijk) allebei op +- 10 tot 12 meter. Liefst met een I/O expander ter plaatse omdat ik anders per plaats/locatie 10 draden moet trekken (4 draden L298N, 2 draden terugmelding, 2 draden led aansturing, en 2 voor drukknoppen). Om dit te vermijden wou ik dus I2C gebruiken maar zoals mas3 het aangeeft is dit afstand niet mogelijk blijkbaar..

Enige suggestie?

Ik weet zo de het volledige nummer niet.

Hoe denk je dat I2C werkt? Dat zijn ook 1 en 0 :wink:

Misschien kun je de beschrijving open een andere manier uitleggen omdat ik het niet helemaal begrijp. Een sketch draait op een Uno; dus al je de sketch op verschillende plaatsen wilt gebruiken zou je meerdere Unos moeten hebben. Of je hebt een centrale Uno en wilt lange draden gebruiken naar een of meer plaatsen.

Als voorbeeld de tca9548 ?

Ja klopt, maar met de library van rob tilaart en de pcf8575 moest k geen bytes intypen, enkel de commands geven en verwijzen zoals pinnummer output en high en low.

Zoals je al deels begrepen hebt, wil k deze sketch op de uno of nano zetten. Die zal vervolgens de H-brug (L298N) aansturen die vervolgens mijn motoren aansturen.. de uno bv in de living gelijkvloer laten en de h-burg, motoren, leds, drukknoppen op het eerste verdiep zetten.. dat wil k ook op het 2de verdiep zetten en de sketch in de uno verdubbelen met andere adres of pinnen.. maar wil hiervoor geen 10 draden naar elke H-brug etc trekken.. daarvoor wou ik de I2C gebruiken maar die kan die afstanden dus niet aan zo te begrijpen..
Ps: de verdiepen zijn als voorbeeld.

Nee, dat is een I2C multiplexer. i2c extender ic - Google Search

Ik zou een Arduino op iedere verdieping gebruiken. Hoeveel Arduinos praten we dan over in totaal?

Met een extender kan je je i2c bus verlengen tot 100meter via een shielded twisted pair kabel lees ik opt net? Zou dit kunnen kloppen? Ma ja, dan heb ik nog altijd een pcb nodig dat tegelijk in en outputs kan beheren terwijl de pcf8575 enkel als inputs of enkel als outputs kunnen dienen. Oftewel moet k 2 pfc8575 gebruiken waarvan 1 inputs en andere outputs. Op deze manier zullen mijn i2c adresse. Snel opgebruikt worden en of zal ik dat tca9548 moeten gebruiken. Of ben ik te ver aan het redeneren?

1 master en 3 of 4 slaves, 4-5 in totaal. Dat is dan weer een hoop, en zou ik makkelijk via een rs485 kunnen communiceren?

Er is wel 1 belangerijk punt, dat is zoals in me sketch te zien is 1 gemeenschappelijke pomp die aan en uit wordt gezet door de master aan de hand van bepaalde voorwaardes in de sketch. Duq de communicatie is een punt dat ik moet oplossen

Ik zou met RS485 gaan werken.
Ook daar werk je dan met adressen zodat je elke slave apart kunt aanspreken (een ander woord is adresseren).
De master is dan de baas en die kan nog steeds de belangrijke taken op zich nemen zoals je pomp.
Gebruik twisted pair kabels tussen de apparaten, veelal kom je dan op een netwerkkabel uit.
Dan kun je de overige 3 pairs wellicht gebruiken voor voeding.
Voordeel van elke verdieping een Arduino, is dat je dan ook op elke verdieping een aantal i/o inclusief 6 analoge ingangen ter beschikking hebt.
Overigens is de L298 leuk om eens mee te experimenteren, maar die is niet erg efficiënt.
Ik raad je aan andere motorshields te overwegen omdat die veel efficiënter met de vermogens omgaan.
Een shield betekent over het algemeen dus ook een Uno.
Sowieso heb je voor het aansturen van motoren en/of ventielen middels zo'n shield, wel een aparte voeding nodig voor dat gedeelte.

thx mas3,
ben al wat aan het bekijken/bestuderen hoe dit in elkaar zit om via RS485 te werken. er wordt geregeld MASTER_EN en SLAVE_EN gebruikt. dus zou dit dan in mijn geval Master_EN; SLAVE1_EN; SLAVE2_EN; etc... worden ? ook merk ik dat dit makkelijk via functie oproeping werkt en niet met bytes wat voor mij al makkelijker is. is het zo dat ik naast de tx en rx aansluiting ook een draad moet leggen naar 1 van de pinnen ?

het is idd een voordeel op elke verdieping een arduino te plaatsen, maar moest ik dit zeer uitgebreid willen maken zou dit dan aan de duurdere kant uitvallen. het is wel zo dat ik per verdiep zon 8 outputs en 3 inputs nodig heb. zelfs op 1 verdiep heb ik 14 outputs en 4 inputs nodig.

ik kan voor iedere verdiep een aparte voeding voorzien via een transfo 220- 5V 2A

die L298N is redelijk prettig. welke efficiëntere shield raad je dan aan ? DRV8833?

RS485 is ideaal hiervoor. Gewoon UTP of STP kabel is niet 100% ideaal. Gewone netwerkkabel heeft een impedantie van 100Ω. RS485 is 120Ω. Maar 120Ω kabel is een stuk duurder.

Waarom geen PCB tekenen met 14 outputs en 4 inputs + TX, RX en TX_EN(able) en daar een ATmega48/88/168 op met een MAX485 voor de communicatie? Kosten bij jlcpcb of seeed een paar euro. Zelfs zonder gebruik van een librarie is de communicatie geen rocket scene. Standaard staat de MAX485 in ontvangstmode. Ontvangen gebeurd hetzelfde als gewone uart communicatie. Om te verzenden pen hoog maken en via een Serial.print() verzenden en voldoende tijd voorzien om te verzenden.

Wil je adressen niet vast inprogrammeren? Dan heb je nog enkele ingangen nodig om adressen in te stellen. Mogelijk moet je dan naar een andere AVR overschakelen.

Programmeren doe je dan via ISP.

In industriële omgeving wordt RS485 het vaakst toegepast. Maar dan onder de naam modbus.

Een print maken zal voor jou niet zo bijzonder zijn, maar voor anderen zal dat een enorme drempel zijn
Hetzelfde geldt voor de communicatie.
Geen rocket science, maar TS geeft al aan dat ie er nog maar net mee begint en zal er dus best nog het een en ander voor moeten leren.
Dat gaat nou eenmaal gemakkelijker als er libraries gebruikt kunnen worden die je veel uit handen nemen.
Wanneer je echt wil leren hoe de vork in de steel zit, ga je het helemaal zelf uitwerken en leg je de library naast je neer.
Maar dan ben je vanaf het nulpunt nog wel een heel stuk studeren verder.

Voor wat betreft de kabels, de lengtes van enkele meters waarover hier gesproken wordt maken het wat minder kritisch dan wanneer je de 1000+ meter waar die impedantie op berekend is wil overbruggen.
Het belangrijkste is dan dat je die twisted pairs gaat gebruiken.

Hi buckfast_beekeeper
Thx voor je opmerking, het is idd die richting dat ik later wil uitgaan. Een pcb met een microcontroller, max485 commununicatie, h-brug of transistoren om motoren te bedienen op 5v/ 40mA puls stromen. allemaal vast geadressseerd. Klopt, heb gelezen dat 0 in lees/ontvangst mode zit en 1 schrijf/zend mode. Dat men daarna wat tijd moet geven "flushen" om het te laten verwerken. Heb al wat geprobeerd met freepcb. Maar Een pcb opstellen is voor mij nog onbekend terrein. Ik wil hiervoor wel een iets voor geven als iemand dat voor mij kan maken maar ik wil het zelf ook leren/begrijpen. Persoonlijk ben ik iemand die aldoende leert, met lezen en leren wat minder.
Zoals MAS3, weeral een goede opmerking, zegt is de weerstand van de kabel minder belangerijk omdat we hier over afstanden hebben van 10meter (mss later max 20meters). Maar dan nog in het slechtste geval kan ik weerstanden plaatsen (vb. 20meter x 20ohm) om het te 'evenaren'. In ieder kzal met stp kabels werken. heb reeds een aantal rs485 en nog een paar nano besteld.. in afwachting dus.
Ik wil jullie allemaal alvast bedanken en zal jullie nog geregeld lastig vallen voor hulp of een update

Bij het leggen van de communicatie is het belangrijk dat de 'nodes' allemaal op 1 lange lijn zitten. Geen ster maken waar er een kabel van de master naar elke node vertrekt. Volgorde van de nodes is onbelangrijk. Aan elk uiteinde zet je een weerstand van 120Ω. Als je gebruik maakt van afgeschermde kabel, dan de afscherming maar aan 1 zijde aan gnd hangen.

Ik gebruik al vele jaren Eagle PCB. Als je Fusion 360 zou hebben, dan kan je ook Eagle PCB gebruiken tot 160mm2. In de free versie is dat 80mm2. Er staan mooie tutorials on-line. Voor iemand een PCB tekenen is minder eenvoudig. Persoonlijk heb je een gedacht waar je bepaalde aansluitingen gaat maken. Hoeveel ervaring heb je met solderen? Kan je met SMD overweg of niet? Als je met SMD kan werken, hoe klein mogen de componenten zijn?

Tja als een output hoog of laag maken en Serial.print het grootste probleem vormt dan zullen er nog grotere uitdagingen volgen.

De RS485/modbus librarie bevat ook CRC. Is dat bij deze afstanden en niet industriële omgeving noodzakelijk? Met gewone, zelf getwiste, draad heb ik nog geen foute communicatie kunnen vaststellen op 19200Bd. Voor huis, tuin en keuken gebruik meestal voldoende.

Ik zal wat tutorials bekijken om iets bij te leren voor pcb te kunnen maken..

Het is het simpelste, en hetzelfde zoals in mijn sketch hierboven aangegeven. Een layout kan ik wel tekenen, al dan niet via de pc maar een handmatige schets.

Heb wel wat ervaring met solderen dan een gemiddelde en kan ook wel overweg met smd. Voor de moment is de grootte van weinig belang, later mag het wel zo klein mogelijk zijn maar sterk genoeg voor een lange levensduur.

Het is voornamelijk bedoeld voor huishoudelijke praktijken. Geen industriele toepassing dus.

Snelheid is zeker niet noodzakelijk. Er is genoeg tijd en denk dat k met een baudrate van 9600 al genoeg heb, meer mag altijd natuurlijk.

hey iedereen,

de RS485 modules en de nanos zijn aangekomen.
heb hiermede een half-duplex communicatie tot stand gebracht. wel is waar zoals buckfast_beekeeper het zei, enkele richting (master commandeerd de slave).
ik ga met de tijd wat meer puzzelen om de communicatie 2 way verkeer te krijgen. daarna ga ik mijn sketch er ergens tussen propen en dit op een lange afstand van 10 meter proberen.

Alvast bedankt iedereen voor de hulp en tips!!

De master die de slave commandeert is gangbare praktijk.
Je kunt de master ook laten pollen.
Dan vraagt de master om de beurt of de slaves nog wat te melden hebben.
De slave heeft dan een bepaalde tijd om daar op te reageren.
Die kan dan "nee" antwoorden waardoor de master al naar de volgende slave kan gaan om die te vragen, levert je dan dus wat tijdwinst op.
De slave kan ook met "ja" antwoorden, en meldt daar achteraan hoeveel ie te melden heeft zodat de master daar tijd voor kan reserveren.
Daarna kan de slave dus zijn hart luchten naar de master toe.
Zo behoudt de master zijn functie, en blijft ie dus de baas.

oké, we zijn dus een stapje verder.
heb de 2 weg communicatie ook in orde gekregen door de communicatie kanaal open te zetten voor elke node. dat wil dus zeggen dat ik de DE en de RE pinnen van de RS485 bij alle node op low heb laten staan. als 1 van de node iets te zeggen heeft ( meestal is dat maar een vraag naar 1 zelfde node) zet hij die pinnen op high, zegt ie wat hij te zeggen heeft gaat netjes terug naar ontvangst/luister mode.
de reden dat ik dit zo heb gedaan is omdat :
° dat alle node zouden in principe nooit te samen communiceren.
°de pomp op 1 node zit, die ik eigenlijk master wou maken.
maar eigenlijk zijn alle node de masters en is er maar 1 slave, en dat is de node met de pomp eraan. de motoren die de kleppen bediend, hangt ieders aan zijn eigen node.

het maakt dus niet uit welke node er heeft gesproken/ gevraagd. de pomp moet gewoon werken als er vraag is en de node die de vraag stelt, gaat ook zelf zijn eigen kleppen bedienen.

zo kan het ook echter uitkijken dat er maar een master is (meestal de pomp) en die luistert naar het antwoord van alle slaven anders gezegd er is maar 1 kapitein aan boord