Laserwaterpas ontvanger

Op 7 september 2020 22:38:03 schreef SparkyGSX:
Eh, je moet de andere ingangen wel met weerstandjes omlaag trekken, anders gaan die zweven, en dat zijn ongeldige combinaties.

Dat helpt inderdaad! Echter nu werkt de output nog wel precies verkeerd om. Dus de output is LOW als hij HIGH moet zijn en vice versa. M.a.w. als ik de fototransistor bij een knipperend led van de ontvanger houd gaat mijn output led uit. Als ik hem verduister gaat hij juist aan.

Heb je die LEDs van de uitgang naar de ground of naar de voeding staan? Die 3 uitgangen zijn actief hoog, dus daar zou de LED van de uitgang naar de ground moeten. Het idee was dat je daarmee een relaisboard of zo zou aansturen, en die hebben gewoonlijk een actief hoog signaal nodig.

Als je ze andersom wilt hebben, is dat triviaal op te lossen, door deze 3 regels te voorzien van een uitroepteken (betekend "logisch inverteren", oftewel "niet"), en een paar extra haakjes om duidelijk te maken dat die andere bitmask operatie eerst gedaan wordt.

code:


  // lookup what to do for this state and write to outputs
  digitalWrite( 5, !( Actions[ FilteredInputs ] & MOVE_UP ) );
  digitalWrite( 6, !( Actions[ FilteredInputs ] & MOVE_DOWN ) );
  digitalWrite( 7, !( Actions[ FilteredInputs ] & MOVE_FAST ) );
Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken

Op 8 september 2020 08:55:12 schreef SparkyGSX:
Heb je die LEDs van de uitgang naar de ground of naar de voeding staan? Die 3 uitgangen zijn actief hoog, dus daar zou de LED van de uitgang naar de ground moeten.

Dat is vreemd want de LED staat van Output5 naar de Ground. Dus als ik jou goed begrijp zou dat moeten kloppen en zou ik niet moeten inverteren?

Lambiek

Special Member

Misschien moet de ingang wel geinverteerd worden. Meestal trekken ze de pin naar de gnd. Zelf doe ik dat nooit, vind dat niet logisch.

Als je haar maar goed zit, GROETEN LAMBIEK.

Nee, bij een hoog signaal geen "digitalRead" een waarde 1, en als je een uitgang met "digitalWrite" op 1 schrijft, wordt hij hoog. Ik zie niet direct waar een inverse vandaan zou komen.

Ik zou in ieder geval 3 LEDs aansluiten, op uitgang 5, 6 en 7, dan kun je tenminste zien wat daar gebeurd. Als het kan ook op uitgang A0..A5, dan kun je de interne staat zien, dat is vooral nuttig om te begrijpen hoe het werkt, en informatie te krijgen over die interne staat als het niet werkt.

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken
Lambiek

Special Member

Ik heb mijn laatste code nog wat aangepast, misschien heeft de TS er nog iets aan. Getest zover het kon en bij een andere actie van de leds op de ontvanger veranderen de uitgangen. Er wordt dus niet meer altijd op niveau nul gewacht. En het is nu beveiligt tegen uitloop of buiten bereik.

Op 8 september 2020 10:09:56 schreef SparkyGSX:
Ik zie niet direct waar een inverse vandaan zou komen.

Ja, ik ook niet. Maar het is wel vreemd toch wat de TS beschrijft.

Als je haar maar goed zit, GROETEN LAMBIEK.

Dat is al iets beter, maar ik zie nog wel een paar problemen.

Om te beginnen, ik heb nooit iets met Basic gedaan, dus ik kan het fout hebben, maar ik zie dat je in de gevallen anders dan "neutraal" een GoTo RUN doet in plaats van Return, terwijl je wel op die plaats gekomen bent met een GoSub. Het lijkt me dat je op die manier een stack overflow gaat krijgen.

Daarbij blijf je met het probleem zitten van die 2 LEDs die "tegelijk" knipperen.

Ik heb even een plaatje getekend om duidelijk te maken wat ik bedoel:

Je kunt erop rekenen dat die 2 signalen nooit echt tegelijk komen; als je het geluk hebt op de plaats van één van de groene pijlen te samplen is er niets aan de hand, maar als je op één van de oranje gebieden valt, zie je iets wat niet waar is.

In de routine RUN loop je keihard rondjes, vele duizenden keren per seconde, dus je hebt maar een klein beetje looptijd verschil nodig om één van de twee signalen hoog te zien, terwijl de andere nog niet hoog is, waardoor je dus onterecht naar je routine SCHUIF_OMHOOG of SCHUIF_OMLAAG gaat. Met je nieuwe toevoegingen, waarmee je de "allebei aan" situatie detecteert in die routines, ga je daar ook heel snel weer uit, dus mogelijk worden de relais helemaal niet aangetrokken in die korte tijd, maar netjes is het niet.

Ik geef toe dat dat best een lastig probleem is! Ik heb dat ondervangen met de stabiliteitsdetectie; de status moet 50ms stabiel zijn voordat ik actie onderneem, anders worden alle ventielen dicht gehouden. Wat je in jouw programma zou kunnen doen, is na het detecteren van één van de uiterste LEDs naar een routine gaan waar je, na een korte vertraging, nog een keer naar die 2 ingangen kijkt, en dan beslist of je omhoog, omlaag, of helemaal niets moet doen. Een vertraging van een paar milliseconden is waarschijnlijk al genoeg.

Een andere tekortkoming, al is het niet gespecificeerd, is wat je doet als je helemaal geen signaal meer krijgt, bijvoorbeeld omdat de accu van de ontvanger leeg is. Het is wel zo netjes als je in dat geval de beweging stopt.

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken
Lambiek

Special Member

Op 8 september 2020 17:50:39 schreef SparkyGSX:
Om te beginnen, ik heb nooit iets met Basic gedaan, dus ik kan het fout hebben, maar ik zie dat je in de gevallen anders dan "neutraal" een GoTo RUN doet in plaats van Return, terwijl je wel op die plaats gekomen bent met een GoSub. Het lijkt me dat je op die manier een stack overflow gaat krijgen.

Dat klopt, maar zover als ik weet kun je dat gewoon door elkaar gebruiken.

Daarbij blijf je met het probleem zitten van die 2 LEDs die "tegelijk" knipperen.

Dat zie ik even niet, heb ik ook tijdens het testen niet gezien. Als NIVEAU_BOVEN_1 en NIVEAU_BOVEN_2 knippert dan wordt er een bitje geset en als beide hoog zijn dan wordt er naar GEEN_DETECTIE gesprongen.
Als NIVEAU_BOVEN_1 of NIVEAU_BOVEN_2 alleen knippert gebeurt er niets.

In de routine RUN loop je keihard rondjes, vele duizenden keren per seconde, dus je hebt maar een klein beetje looptijd verschil nodig om één van de twee signalen hoog te zien, terwijl de andere nog niet hoog is, waardoor je dus onterecht naar je routine SCHUIF_OMHOOG of SCHUIF_OMLAAG gaat. Met je nieuwe toevoegingen, waarmee je de "allebei aan" situatie detecteert in die routines, ga je daar ook heel snel weer uit, dus mogelijk worden de relais helemaal niet aangetrokken in die korte tijd, maar netjes is het niet.

De uitgangen worden toch geset, dat is normaal gesproken ook zo bij een ander programma.

Ik geef toe dat dat best een lastig probleem is!

Dat is het ook, zeker als je de laser en de laser-ontvanger er niet bij hebt.

Een andere tekortkoming, al is het niet gespecificeerd, is wat je doet als je helemaal geen signaal meer krijgt, bijvoorbeeld omdat de accu van de ontvanger leeg is. Het is wel zo netjes als je in dat geval de beweging stopt.

Dat gebeurt toch al? Als je in de lus zit waar de ingangen afgevraagd worden en er komt daar geen signaal binnen dan gebeurt er niets.

Als je haar maar goed zit, GROETEN LAMBIEK.

@ Sparky.
Hij werkt nu! Ik heb ontzettend zitten klooien met de Arduino waarbij ik geen nieuwe codes meer kon uploaden. Maar dat lijkt nu weer te werken.
Nu alles aangesloten zit op het breadboard en de fototransistoren (met een tape-je) aan de ontvanger werkt alles zoals de bedoeling is, in de code heb ik nu de inverters weer verwijderd. Het enige wat niet helemaal klopt met het schema welke ik had gegeven is dat ik 4 uitgangen had bedacht en jij met 3 werkt. Maar dat kan ik hydraulisch prima gebruiken, ik zet dan een 4/3 in serie met een 3/2 waarbij 1 zijde over de smoring loopt. Op die manier kan ik goed met maar 3 uitgangen werken. Ik had twee hydraulische opties maar nu heb jij de keuze gemaakt :P

Dan nog een vraag over de code zelf.
Als ik het goed begrijp gaat er een teller teruglopen (vanaf 500ms in dit geval) op het moment dat er een LED blinkt. Als er voor deze tijd een nieuwe blink is blijft hij actief. Maar na hoeveel blinks schakelt hij naar een output HIGH? Hij lijkt namelijk wat langzaam te reageren als ik hem voor de laser houd dus misschien kan ik daar dan wat mee spelen.

Het niet kunnen laden van de software in de UNO kan komen door het gebruik van de digitale ingangen 0 en 1 , die hangen intern aan de usb bus , dus aan de seriele poort . Op de uno staat bij D0 en D1 tx en rx gedrukt .

Op 8 september 2020 19:05:51 schreef Lambiek:
[...]
Dat klopt, maar zover als ik weet kun je dat gewoon door elkaar gebruiken.

Op dit forum http://www.picbasic.co.uk/forum/archive/index.php/t-14074.html staat dat je daar een stack overflow van krijgt, maar ik zou denken dat je dat dan wel een keer gemerkt zou hebben.

Dat zie ik even niet, heb ik ook tijdens het testen niet gezien. Als NIVEAU_BOVEN_1 en NIVEAU_BOVEN_2 knippert dan wordt er een bitje geset en als beide hoog zijn dan wordt er naar GEEN_DETECTIE gesprongen.
Als NIVEAU_BOVEN_1 of NIVEAU_BOVEN_2 alleen knippert gebeurt er niets.

Kijk even naar het plaatje dat ik heb gepost, "tegelijk" bestaat niet, je kunt altijd één van de ingangen eerder zien dan de andere.

De uitgangen worden toch geset, dat is normaal gesproken ook zo bij een ander programma.

Niet bij dat van mij, omdat de status 50ms stabiel moet zijn voordat ik actie ga ondernemen; dat ondervangt het probleem van de looptijd verschillen, maar ook de situatie dat één of meerdere ingangen erratische signalen geven.

Dat gebeurt toch al? Als je in de lus zit waar de ingangen afgevraagd worden en er komt daar geen signaal binnen dan gebeurt er niets.

Ja, maar als je in een andere staat zit, blijf je daar voor altijd hangen, omdat je er geen time-out in hebt gemaakt. Mijn programma stopt automatisch na 500ms, of welke tijd je dan ook instelt, die iets langer zou moeten zijn dan de maximale tijd dat de LEDs uit zijn bij het knipperen.

@TS: mijn idee was om een minium aan ventielen te gebruiken, met inderdaad één ventiel waarmee een smoorventiel overbrugt wordt. Als je er 4 wilt kan dat ook wel, kleine moeite.

Ik kan het programma ook wel even aanpassen zodat D0 en D1 niet meer gebruikt worden, er zijn nog genoeg pinnen over. Ik was vergeten dat die ook gebruikt werden om het programma te laden.

Hij schakelt in principe direct over als er een andere LED gaat knipperen, maar dan moet de 500ms timer van de eerste wel afgelopen zijn, anders is het nog een ongeldige situatie. Ik was uitgegaan van 1 keer per seconde knipperen, waarbij de LEDs dus 500ms uit zijn; als dat veel korter is, kun je die tijd wel aanpassen. Wat je niet wilt, is dat de uitgang bij elke keer knipperen aan- en uit gaat, en dat gebeurd als die vertraging korter is dan de tijd dat de LED uit blijft.

EDIT: Ik had je tabelletje niet gezien; met 4x per seconde knipperen kun je die timer dus op 125ms + marge zetten, dus ik zou ongeveer 200ms proberen.

Zoals het nu is, wordt de situatie "eruit gelopen" aan de boven- of onderkant niet apart gedetecteerd, en als je die timer korter zet, zou daarbij steeds kortstondig het ventiel aangestuurd worden. In de huidige opzet is alle informatie uit het verleden "vergeten" zodra alle timers zijn afgelopen; als je die situaties apart wilt detecteren, moet er behoorlijk wat op de schop.

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken
Lambiek

Special Member

Op 8 september 2020 19:45:10 schreef SparkyGSX:
[...]Op dit forum [/url]http://www.picbasic.co.uk/forum/archive/index.php/t-14074.html[/url] staat dat je daar een stack overflow van krijgt, maar ik zou denken dat je dat dan wel een keer gemerkt zou hebben.

Ik heb het even aangepast, het staat wel netter. :) En ik heb niets gemerkt.

Kijk even naar het plaatje dat ik heb gepost, "tegelijk" bestaat niet, je kunt altijd één van de ingangen eerder zien dan de andere.

Ik set toch een bitje, als er één knippert is er niets aan de hand. Knipperen ze beide dan wordt er naar GEEN_DETECTIE gegaan.

Ik heb het net nog even geprobeerd en wat ik ook doe ik krijg het niet in een fout.

Niet bij dat van mij, omdat de status 50ms stabiel moet zijn voordat ik actie ga ondernemen; dat ondervangt het probleem van de looptijd verschillen, maar ook de situatie dat één of meerdere ingangen erratische signalen geven.

Dat is wel beter, maar gebeurt dat ook dat er één of meerdere ingangen hoog kunnen worden. Ik heb dat niet begrepen van de TS.

Ja, maar als je in een andere staat zit, blijf je daar voor altijd hangen, omdat je er geen time-out in hebt gemaakt. Mijn programma stopt automatisch na 500ms, of welke tijd je dan ook instelt, die iets langer zou moeten zijn dan de maximale tijd dat de LEDs uit zijn bij het knipperen.

Bij jou veranderd de tijd, dat heb ik niet.

Maar maakt verder niet uit, jou programma doet het prima. :)

Als je haar maar goed zit, GROETEN LAMBIEK.

Op 8 september 2020 19:54:43 schreef Lambiek:
Ik set toch een bitje, als er één knippert is er niets aan de hand. Knipperen ze beide dan wordt er naar GEEN_DETECTIE gegaan.

Ik heb het net nog even geprobeerd en wat ik ook doe ik krijg het niet in een fout.

Er is wel een tijd dat ze tegelijk branden, maar ze gaan per definitie niet exact tegelijk aan en uit; het zijn analoge circuits, dus er zal altijd iets verschil in zitten, en je hebt niet meer dan een paar honderd ns nodig voordat het mis gaat. Heb je naar mijn plaatje gekeken? Duidelijker dan dat kan ik het niet maken, denk ik.

Dat is wel beter, maar gebeurt dat ook dat er één of meerdere ingangen hoog kunnen worden. Ik heb dat niet begrepen van de TS.

Expect the unexpected; waar mogelijk moet een stuk software of elektronica goed reageren, of op een veilige manier stoppen, als zich een situatie voordoet die niet zou mogen gebeuren.

Er zou nooit iemand zomaar voor je auto moeten stappen, maar toch is het een goed idee om te remmen of uit te wijken als dat toch gebeurd.

Maar maakt verder niet uit, jou programma doet het prima. :)

Op zich waar, maar het is mijn bedoeling dat jij hier ook van leert, dan hoef ik het de volgende keer niet te schrijven ;-)

@TS: ik ben toch bezig om de "uit bereik gelopen" situatie te detecteren; kun je schatten hoe lang die 2 knippers zijn in die situatie? Ik twijfel tussen het detecteren van die langere tijd, of de gemiddelde duty-cycle. Zijn de LEDs gewoonlijk ongeveer even lang aan als uit? Zijn ze bij die "uit bereik gelopen" veel korter aan dan uit?

EDIT: toegevoegd; werderom, niet getest, dat mag de TS doen.

code:

#define MAX_INTERVAL 200 // max time a LED can be off while blinking, in ms
#define STABILITY_THRESHOLD 50 // time the input state must be stable before movement starts, in ms

#define DO_NOTHING  0x00
#define MOVE_UP   0x01
#define MOVE_DOWN 0x02
#define MOVE_FAST 0x04
#define MOVE_UPFAST (MOVE_UP | MOVE_FAST)
#define MOVE_DOWNFAST (MOVE_DOWN | MOVE_FAST)

// what to do for each combination of inputs; any combination of 2 or more active inputs means
// do nothing, only the combinations with exactly one active input, except the middle (neatral) input
// result in movement. These are positions 0x01 (1) for up fast, 0x02 (2) for up slow, 0x04 (4) for neutral,
// 0x08 (8) for down slow, 0x10 (16) for down fast. Note the array index starts at 0
const unsigned char Actions[ 32 ] = 
  { DO_NOTHING, MOVE_UPFAST, MOVE_UP, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, // 0..7
    MOVE_DOWN, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, // 8..15
    MOVE_DOWNFAST, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, // 16..23
    DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING }; // 24..31

unsigned short InputCounters[ 5 ] = { 0, 0, 0, 0, 0 };
unsigned char ReadInputs, FilteredInputs, PreviousInputs = 0;
unsigned long StabilityCount = 0, ActivityCounter = 0;

void setup()
{
  pinMode( 2, INPUT ); // input top LED
  pinMode( 3, INPUT );
  pinMode( 4, INPUT );
  pinMode( 5, INPUT );
  pinMode( 6, INPUT ); // input bottom LED
  pinMode( 7, OUTPUT ); // move UP output
  pinMode( 8, OUTPUT ); // move DOWN output
  pinMode( 9, OUTPUT ); // move FAST output
  pinMode( 10, OUTPUT ); // Fout uitgang
  
  pinMode( A0, OUTPUT ); // Debugging status LEDs
  pinMode( A1, OUTPUT );
  pinMode( A2, OUTPUT );
  pinMode( A3, OUTPUT );
  pinMode( A4, OUTPUT );
  pinMode( A5, OUTPUT );
}

void loop()
{
  unsigned char Index;
  
  FilteredInputs = 0;
  ReadInputs = ( digitalRead( 2 ) ) | ( digitalRead( 3 ) << 1 ) | ( digitalRead( 4 ) << 2 ) | ( digitalRead( 5 ) << 3 ) | ( digitalRead( 6 ) << 4 );

  // this loop monitors each input for recent activity; when an input is active, the timer for that inputs
  // is set to MAX_INTERVAL, and starts counting down from there; when it reaches 0, the input is considered
  // inactive. MAX_INTERVAL should be set slightly longer than the maximum time the LED for an input can be off
  // when blinking
  for( Index = 0; Index < 5; Index++ )
  {
    if( ReadInputs & ( 1 << Index ) )
      InputCounters[ Index ] = MAX_INTERVAL;

    if( InputCounters[ Index ] )
    {
      InputCounters[ Index ]--;
      FilteredInputs |= 1 << Index;
    }

    // write each input filter status to a debug LED (A0 + 3 is the same as A3)
    digitalWrite( A0 + Index, !InputCounters[ Index ] );
  }

  if( !FilteredInputs ) // if all timers have expired, not a single input active
    ActivityCounter = 2000; // set timer for 2 seconds; only when signal is lost should all timers expire

  if( ActivityCounter )
  {
    ActivityCounter--;
    FilteredInputs = 0; // only after 2 seconds without any expired timers should the outputs become active
  }
  
  // now check if the input state has been stable for a number of successive cycles, to prevent movement
  // when 2 LEDs are blinking, since one can always be detected slightly earlier or later than the other
  // If current and previous input states are different, reset stability counter
  if( PreviousInputs != FilteredInputs )
    StabilityCount = STABILITY_THRESHOLD;

  // now store the current input state for the next cycle
  PreviousInputs = FilteredInputs;

  // if stability counter has not yet reached the threshold, increment it, and force the input state to 0
  // to prevent any movement
  if( StabilityCount )
  {
    StabilityCount--;
    FilteredInputs = 0;
  }
  
  // write Stability status to debug LED
  digitalWrite( A5, !StabilityCount );

  // write Error LED status; LOW when an error occured (LED with resistor to supply)
  digitalWrite( 10, FilteredInputs );
  
  // lookup what to do for this state and write to outputs
  digitalWrite( 7, Actions[ FilteredInputs ] & MOVE_UP );
  digitalWrite( 8, Actions[ FilteredInputs ] & MOVE_DOWN );
  digitalWrite( 9, Actions[ FilteredInputs ] & MOVE_FAST );

  delay(1); // actual loop interval will be slightly longer, because it also takes some time to execute
}

Ik heb de interval korter gemaakt, en een extra timer toegevoegd; hij moet minimaal 2 seconde lang knipperende LEDs hebben gezien, met een interval van maximaal 200ms, voordat de uitgangen actief worden.

Daarbij heb ik de in- en uitgangen opgeschoven, zodat D0 en D1 vrij zijn, en uitgang D10 toegevoegd, met het doel dat daar een LED aan komt die aan de bestuurder kan aangeven dat er iets fout is, en het systeem inactief is geworden.

EDIT: stommiteitje met bitshifts van de ingangen opgelost.

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken

Op 8 september 2020 19:29:43 schreef Lead Acid:
Het niet kunnen laden van de software in de UNO kan komen door het gebruik van de digitale ingangen 0 en 1 , die hangen intern aan de usb bus , dus aan de seriele poort . Op de uno staat bij D0 en D1 tx en rx gedrukt .

Ah vandaar dat ik het wel voor elkaar kreeg als ik de boel losgooide. Zeer goed om te weten!

Op 8 september 2020 19:45:10 schreef SparkyGSX:
@TS: mijn idee was om een minium aan ventielen te gebruiken, met inderdaad één ventiel waarmee een smoorventiel overbrugt wordt. Als je er 4 wilt kan dat ook wel, kleine moeite.

Niet nodig, ik ga het gewoon met die 3 uitgangen doen. Des te minder, des te beter!

Op 8 september 2020 19:45:10 schreef SparkyGSX:
Ik kan het programma ook wel even aanpassen zodat D0 en D1 niet meer gebruikt worden, er zijn nog genoeg pinnen over. Ik was vergeten dat die ook gebruikt werden om het programma te laden.

Dat gaat me zelf wel lukken denk ik.

Op 8 september 2020 19:45:10 schreef SparkyGSX:
Zoals het nu is, wordt de situatie "eruit gelopen" aan de boven- of onderkant niet apart gedetecteerd, en als je die timer korter zet, zou daarbij steeds kortstondig het ventiel aangestuurd worden. In de huidige opzet is alle informatie uit het verleden "vergeten" zodra alle timers zijn afgelopen; als je die situaties apart wilt detecteren, moet er behoorlijk wat op de schop.

Dat kortstondig aansturen gebeurt nu ook al met die 500ms.

Op 8 september 2020 20:32:37 schreef SparkyGSX:
@TS: ik ben toch bezig om de "uit bereik gelopen" situatie te detecteren; kun je schatten hoe lang die 2 knippers zijn in die situatie? Ik twijfel tussen het detecteren van die langere tijd, of de gemiddelde duty-cycle. Zijn de LEDs gewoonlijk ongeveer even lang aan als uit? Zijn ze bij die "uit bereik gelopen" veel korter aan dan uit?

De 2 knippers gaan met +/- dezelfde frequentie als wanneer er wel bereik is. Daarna blijft hij +/-1sec uit alvorens hij weer opnieuw 2x knippert.

Lambiek

Special Member

Op 8 september 2020 20:32:37 schreef SparkyGSX:
Op zich waar, maar het is mijn bedoeling dat jij hier ook van leert, dan hoef ik het de volgende keer niet te schrijven ;-)

Dat doe je zelf, dat schrijven. :)
En ik ben met pensioen dus. :) En ik ga zeker niets met Arduino's doen.

Maar even iets anders, ik neem aan dat er een kleine hysterese zit in de ontvanger tussen de verschillenfe niveaus. Anders zou je met een gekocht systeem ook problemen hebben, of zie ik dat verleerd.

Als je haar maar goed zit, GROETEN LAMBIEK.

@ Sparky. Deze nieuwe code werkte niet naar behoren. Ik was zelf ook al bezig geweest met het aanpassen van de poorten en had hem in eerste instantie aangepast met oa de regel zoals jij hem hieronder ook hebt aangepast.

Op 8 september 2020 20:32:37 schreef SparkyGSX:
ReadInputs = ( digitalRead( 2 ) << 2 ) | ( digitalRead( 3 ) << 3 ) | ( digitalRead( 4 ) << 4 ) | ( digitalRead( 5 ) << 5 ) | ( digitalRead( 6 ) << 6 );

Ik kwam erachter dat dat niet goed werkte en heb daarna alleen de poortnr's tussen de haakjes aangepast om te proberen, dit werkt wel maar ik heb geen idee wat ik daar precies mee gedaan heb. Kan jij dit verklaren? De regel is dan als volgt:
ReadInputs = digitalRead( 2 ) | ( digitalRead( 3 ) << 1 ) | ( digitalRead( 4 ) << 2 ) | ( digitalRead( 5 ) << 3 ) | ( digitalRead( 6 ) << 4 );

Ja de verklaring is dat ik zat te slapen, elk van die "digitalRead()" functies geeft 0 of 1 terug, dus de bitshift moet juist niet veranderen. Jouw regel is correct. Ik heb de code in mijn vorige bericht gecorrigeerd.

Ik ben gewend om hele poorten ineens te lezen, in plaats van losse bits, en dan moet je ze wel altijd opschuiven, vandaar de verwarring.

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken

Ok, als ik het dan goed begrijp leest hij bij HIGH signaal:
input 2 = 1
input 3 = 2
input 4 = 4
input 5 = 8
input 6 = 16
Klopt dit? En zo ja waarom gebruik je dit? (Heeft niks met de werking te maken maar ik probeer de code voor mezelf te begrijpen.)

Correct; dat doe ik om vervolgens in de loop eenvoudig bij de status van elk van die bits te kunnen. Het was ook mogelijk geweest om in de loop digitalRead( Index + 2 ) te doen, maar dan moeten ze verplicht direct achter elkaar, en in de juiste volgorde op de I/O pinnen zitten; zoals ik het nu heb opgelost, ben je in principe vrij om met die signalen te schuiven, bijvoorbeeld als je een bijzondere functie van één van de pinnen zou willen gebruiken (PWM output bijvoorbeeld), waardoor de signalen niet meer direct achter elkaar zijn aangesloten.

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken

Op 9 september 2020 12:04:36 schreef SparkyGSX:
Correct; dat doe ik om vervolgens in de loop eenvoudig bij de status van elk van die bits te kunnen. Het was ook mogelijk geweest om in de loop digitalRead( Index + 2 ) te doen, maar dan moeten ze verplicht direct achter elkaar, en in de juiste volgorde op de I/O pinnen zitten; zoals ik het nu heb opgelost, ben je in principe vrij om met die signalen te schuiven, bijvoorbeeld als je een bijzondere functie van één van de pinnen zou willen gebruiken (PWM output bijvoorbeeld), waardoor de signalen niet meer direct achter elkaar zijn aangesloten.

Ok dit gaat mijn pet duidelijk te boven maar ik begrijp de insteek!

Ik heb nog even zitten de spelen met de ontvanger en de laatste code en hij werkt nu super. Hij schakelt sneller, en bij een "eruit gelopen" signaal doet hij niks.
Verder zijn er nog twee dingen die ik er graag aan toe zou willen voegen. Ten eerste een signaalknop (met indicatielampje) om het systeem op "automatisch" in te schakelen.
En ten tweede een joystick voor handbediening. Mijn idee is om het systeem automatisch naar "handmatig" te zetten op het moment dat de joystick omhoog of naar beneden bediend wordt. Wil je daarna weer automatisch gaan werken dan druk je de knop weer in. Het signaal van de drukknop moet dus feitelijk HIGH blijven totdat er een signaal vanaf de joystick komt.

Is dit nog in de code in te bouwen? En zou je dan de relais direct schakelen met de joystick of met de outputs van de Arduino zoals gebruikt in de "automatische modus"?

Kleine moeite

code:

#define MAX_INTERVAL 200 // max time a LED can be off while blinking, in ms
#define STABILITY_THRESHOLD 50 // time the input state must be stable before movement starts, in ms

#define DO_NOTHING  0x00
#define MOVE_UP   0x01
#define MOVE_DOWN 0x02
#define MOVE_FAST 0x04
#define MOVE_UPFAST (MOVE_UP | MOVE_FAST)
#define MOVE_DOWNFAST (MOVE_DOWN | MOVE_FAST)

// what to do for each combination of inputs; any combination of 2 or more active inputs means
// do nothing, only the combinations with exactly one active input, except the middle (neatral) input
// result in movement. These are positions 0x01 (1) for up fast, 0x02 (2) for up slow, 0x04 (4) for neutral,
// 0x08 (8) for down slow, 0x10 (16) for down fast. Note the array index starts at 0
const unsigned char Actions[ 32 ] = 
  { DO_NOTHING, MOVE_UPFAST, MOVE_UP, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, // 0..7
    MOVE_DOWN, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, // 8..15
    MOVE_DOWNFAST, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, // 16..23
    DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING }; // 24..31

unsigned short InputCounters[ 5 ] = { 0, 0, 0, 0, 0 };
unsigned char ReadInputs, FilteredInputs, PreviousInputs = 0, AutomaticMode = 0, JoystickInput;
unsigned long StabilityCount = 0, ActivityCounter = 0;

void setup()
{
  // pin 0 unused; causes problems when loading new software
  pinMode( 1, OUTPUT ); // LED for automatic mode
  pinMode( 2, INPUT ); // input top LED
  pinMode( 3, INPUT );
  pinMode( 4, INPUT );
  pinMode( 5, INPUT );
  pinMode( 6, INPUT ); // input bottom LED
  pinMode( 7, OUTPUT ); // move UP output
  pinMode( 8, OUTPUT ); // move DOWN output
  pinMode( 9, OUTPUT ); // move FAST output (low=fast)
  pinMode( 10, OUTPUT ); // Error output
  pinMode( 11, INPUT ); // pushbutton for automatic mode
  pinMode( 12, INPUT ); // joystick UP
  pinMode( 13, INPUT ); // joystick DOWN
  pinMode( A0, OUTPUT ); // Debugging status LEDs
  pinMode( A1, OUTPUT );
  pinMode( A2, OUTPUT );
  pinMode( A3, OUTPUT );
  pinMode( A4, OUTPUT );
  pinMode( A5, OUTPUT );
}

void loop()
{
  unsigned char Index;
  
  FilteredInputs = 0;
  ReadInputs = ( digitalRead( 2 ) ) | ( digitalRead( 3 ) << 1 ) | ( digitalRead( 4 ) << 2 ) | ( digitalRead( 5 ) << 3 ) | ( digitalRead( 6 ) << 4 );

  // this loop monitors each input for recent activity; when an input is active, the timer for that inputs
  // is set to MAX_INTERVAL, and starts counting down from there; when it reaches 0, the input is considered
  // inactive. MAX_INTERVAL should be set slightly longer than the maximum time the LED for an input can be off
  // when blinking
  for( Index = 0; Index < 5; Index++ )
  {
    if( ReadInputs & ( 1 << Index ) )
      InputCounters[ Index ] = MAX_INTERVAL;

    if( InputCounters[ Index ] )
    {
      InputCounters[ Index ]--;
      FilteredInputs |= 1 << Index;
    }

    // write each input filter status to a debug LED (A0 + 3 is the same as A3)
    digitalWrite( A0 + Index, !InputCounters[ Index ] );
  }

  if( !FilteredInputs ) // if all timers have expired, not a single input active
    ActivityCounter = 2000; // set timer for 2 seconds; only when signal is lost should all timers expire

  if( ActivityCounter )
  {
    ActivityCounter--;
    FilteredInputs = 0; // only after 2 seconds without any expired timers should the outputs become active
  }
  
  // now check if the input state has been stable for a number of successive cycles, to prevent movement
  // when 2 LEDs are blinking, since one can always be detected slightly earlier or later than the other
  // If current and previous input states are different, reset stability counter
  if( PreviousInputs != FilteredInputs )
    StabilityCount = STABILITY_THRESHOLD;

  // now store the current input state for the next cycle
  PreviousInputs = FilteredInputs;

  // if stability counter has not yet reached the threshold, increment it, and force the input state to 0
  // to prevent any movement
  if( StabilityCount )
  {
    StabilityCount--;
    FilteredInputs = 0;
  }
  
  // write Stability status to debug LED
  digitalWrite( A5, !StabilityCount );

  // write Error LED status; LOW when an error occured (LED with resistor to supply)
  digitalWrite( 10, FilteredInputs );

  JoystickInput = digitalRead( 12 ) | ( digitalRead( 13 ) << 1 ); // 0x01 = UP, 0x02 = DOWN

  if( JoystickInput )
    AutomaticMode = 0;
  else
    if( digitalRead( 11 ) ) // pushbutton for automatic mode
      AutomaticMode = 1;

  if( AutomaticMode )
  {
    // lookup what to do for this state and write to outputs
    digitalWrite( 7, Actions[ FilteredInputs ] & MOVE_UP );
    digitalWrite( 8, Actions[ FilteredInputs ] & MOVE_DOWN );
    digitalWrite( 9, !( Actions[ FilteredInputs ] & MOVE_FAST ) );
  }
  else
  {
    digitalWrite( 7, JoystickInput == 0x01 ); // valve UP when joystick UP is active (and DOWN isn't)
    digitalWrite( 8, JoystickInput == 0x02 ); // valve UP when joystick DOWN is active (and UP isn't)
    digitalWrite( 9, 0 ); // fast mode
  }

  digitalWrite( 1, AutomaticMode );
  delay(1); // actual loop interval will be slightly longer, because it also takes some time to execute
}

Drukknopje voor automatisch op ingang 11, joystick omhoog op 12, omlaag op 13. Allemaal pull-down weerstanden geven, schakelaar naar 5V voor actief signaal.

Nu gaat hij langzaam, is het de bedoeling dat het ventiel voor snel bewegen ook aangestuurd wordt?

Het wordt zo langzamerhand wel tijd om de in- en uitgangen een naam te geven, het begon heel simpel, maar nu zijn alle pinnen gebruikt!

Ik heb pin D1 gebruikt voor een LED die aangeeft dat de automatische mode aan staat; als het goed is, geeft dat geen problemen met het laden van nieuwe software, omdat D1 de TX pin is, en de bootloader die overneemt bij het laden.

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken

Op 9 september 2020 23:02:53 schreef SparkyGSX:
Kleine moeite

Voor jou ja :) Wederom bedankt!

Op 9 september 2020 23:02:53 schreef SparkyGSX:
Drukknopje voor automatisch op ingang 11, joystick omhoog op 12, omlaag op 13. Allemaal pull-down weerstanden geven, schakelaar naar 5V voor actief signaal.

Is inmiddels aangesloten en dit werkt goed, echter nu werkt de "automatische modus" niet meer zoals hij voorheen deed |:( . Hij reageert niet meer op de bovenste en 2 onderste lampjes, de tweede van boven werkt wel goed en de neutraal stand geeft nu de actie zoals het bovenste lampje zou moeten doen. Er zit ergens een bug dus.

Op 9 september 2020 23:02:53 schreef SparkyGSX:
Nu gaat hij langzaam, is het de bedoeling dat het ventiel voor snel bewegen ook aangestuurd wordt?

Ja voor handbediening wil ik de snelle uitgang gebruiken. Maar dit zou ik bij nader inzien anders in de besturing willen hebben. Ik wil eigenlijk dat de snelle stand over de niet-bekrachtigde stand van het ventiel loopt en bij de langzame stand het ventiel gebruikt wordt. Dit omdat we dan de machine nog steeds volledig hydraulisch kunnen gebruiken zoals hij nu is.
De handmatige bediening is dus wel goed nu maar dan zullen we dit in de automatische modus om moeten draaien.

Op 9 september 2020 23:02:53 schreef SparkyGSX:
Het wordt zo langzamerhand wel tijd om de in- en uitgangen een naam te geven, het begon heel simpel, maar nu zijn alle pinnen gebruikt!

Eens! Maar dat zal wel moeten lukken denk ik.

Op 9 september 2020 23:02:53 schreef SparkyGSX:
Ik heb pin D1 gebruikt voor een LED die aangeeft dat de automatische mode aan staat; als het goed is, geeft dat geen problemen met het laden van nieuwe software, omdat D1 de TX pin is, en de bootloader die overneemt bij het laden.

Klopt, dit werkt goed en laden gaat zonder problemen.

Ah, shit, die bitshift bug had ik in mijn lokale file niet gefixed. Ik heb de code aangepast. Ik heb ook de FAST uitgang geïnverteerd.

[Bericht gewijzigd door SparkyGSX op 10 september 2020 16:45:01 (18%)]

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken

Op 10 september 2020 16:41:32 schreef SparkyGSX:
Ah, shit, die bitshift bug had ik in mijn lokale file niet gefixed.

8)7 Dat had ik zelf nog wel kunnen zien.

Ondertussen ben ik bezig met de behuizing welke ik op de ontvanger wil kunnen schroeven met daarin een printplaatje om het signaal uit te lezen. (zie bijlage) Is er hier iemand die weet hoe en waar ik een proto PCB kan bestellen? Ik heb op een ander deel van dit forum al eea gelezen over leveranciers maar ik ben er vrij zeker van dat zij niet zoveel met mijn ontwerp kunnen.

Lambiek

Special Member

Op 10 september 2020 19:21:30 schreef BartL:
Ondertussen ben ik bezig met de behuizing welke ik op de ontvanger wil kunnen schroeven met daarin een printplaatje om het signaal uit te lezen. (zie bijlage)

Zie ik nu twee printjes? Of kijk ik verleerd?

Wat is de afstand van je laser ontvanger tot aan je controller? Dit vraag ik inverband met eventuele storing.

Als je haar maar goed zit, GROETEN LAMBIEK.