Laserwaterpas ontvanger


Ja, dat lijkt me wel het gemakkelijkst.

Wat is je bedoeling met de rest van dit project? Er moet nog wel wat gebeuren voordat dit geschikt is voor montage op een voertuig. Het zal mechanisch solide moeten worden gebouwd, met bescherming tegen vocht en vuil, en je hebt ook nog wel wat nodig om de voeding te beschermen.

@Lambiek: zo'n kabel direct aan de ingangen in inderdaad echt geen goed idee, maar 10k in serie met 100nF naar de ground is meestal goed genoeg; die AVR heeft goede interne clamping diodes (net als PICs trouwens).

Die optocouplers zijn niet perse een slecht idee hoor, maar ik vind het wat overdreven. Het ligt er ook aan hoe de TS hier verder mee wil gaan; als je een board gaat ontwerpen kun je zoiets simpel doen, als het een samenstelling van een Arduino, ingekocht relaisboard, en een protoshield of zo moet worden, gaat dat al moeilijk worden.

Waar kan die negatieve spanning vandaan komen of door wat kan dat veroorzaakt worden?

Die negatieve pieken komt van opslingering van kabels door het abrupt uitschakelen van verbruikers, voornamelijk de injectors en bobines. In de ISO normen staat dat allemaal beschreven, en ISO 7637-2 is online wel te vinden.

Hoe bedoel je dat, een diode in serie met de relais spoel? Dus in doorlaat tussen plus en relais of anders?

Ja, in serie met de inkomende voeding; bij een negatieve piek gaat de diode parallel aan het relais in geleiding, en komt die piek dus helemaal over de transistor te staan, in een richting die hij echt niet leuk vind.

In de praktijk valt het vaak wel mee met die rommel op het boordnet, de telefoonladers met alleen een 7805 of MC34063 zonder enige beveiligingen blijven vaak ook nog wel een tijdje heel (maar uiteindelijk gaan ze altijd, is mijn ervaring). Het is zo'n kleine moeite om een paar maatregelen te nemen, dat ik dat zeker zou doen.

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

Op 12 september 2020 09:42:04 schreef SparkyGSX:
Wat is je bedoeling met de rest van dit project? Er moet nog wel wat gebeuren voordat dit geschikt is voor montage op een voertuig. Het zal mechanisch solide moeten worden gebouwd, met bescherming tegen vocht en vuil, en je hebt ook nog wel wat nodig om de voeding te beschermen.

Welke voeding bedoel je? De 12V komt vanaf de accu dus dat zit wel goed. En vwb montage, dat is nou net iets waar ik wél goed in ben!

Lambiek

Special Member

Op 12 september 2020 09:42:04 schreef SparkyGSX:
@Lambiek: zo'n kabel direct aan de ingangen in inderdaad echt geen goed idee, maar 10k in serie met 100nF naar de ground is meestal goed genoeg;

Dat bedoel ik dus ook, een kabel van 7 meter is een pracht van een antenne voor allerlei troep. Dus vandaar die optocoupler aan de ingang met het filter.

Die optocouplers zijn niet perse een slecht idee hoor, maar ik vind het wat overdreven.

Dus jij zou zeggen houd de ingangen op 5VDC met een weerstand van 10K in serie met de ingang en een 100nF naar de gnd.

Die negatieve pieken komt van opslingering van kabels door het abrupt uitschakelen van verbruikers, voornamelijk de injectors en bobines.

Maar dit is een diesel "neem ik aan" en daar heb je geen ontsteking met bobines. En de injectors gaan via een brandstofpomp neem ik aan, al zijn er ook tractoren waarbij de injectie elektronisch geregeld wordt.

Ja, in serie met de inkomende voeding;

Op deze manier dus.

In de praktijk valt het vaak wel mee met die rommel op het boordnet, de telefoonladers met alleen een 7805 of MC34063 .....

Ik had daar het liefst een schakelende voeding gezien.
Zoiets dus.

https://nl.rs-online.com/web/p/switching-regulators/9068487/

Als je haar maar goed zit, GROETEN LAMBIEK.

@TS: de 12V vanaf je accu is geen "schone" 12V, het is verstandig om een beetje beveiliging te voorzien, om de ergste rommel buiten de deur te houden. Nu is de load dump in ISO 7637-2 en ISO 16750-2 wel erg ruig; 80V op een 12V systeem (dat is wanneer de dynamo de accu stevig aan het laden is, en de verbinding naar die accu verbroken wordt).

Zo'n voeding als Lambiek voorstelt is prima, als je daar even een seriediode voor zet, met een bufferelco met keramische of MKP parallel, en als je het goed wilt doen nog een TVS voor de korte en hoge pieken.

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

Special Member

Op 12 september 2020 10:29:54 schreef SparkyGSX:
Zo'n voeding als Lambiek voorstelt is prima, als je daar even een seriediode voor zet, met een bufferelco met keramische of MKP parallel, en als je het goed wilt doen nog een TVS voor de korte en hoge pieken.

Zo iets dus.

Hier heb ik nog een opmerking over.

zo'n kabel direct aan de ingangen in inderdaad echt geen goed idee, maar 10k in serie met 100nF naar de ground is meestal goed genoeg;

Ik zie daar toch liever nog een pull-down van 10K, maar als je dat doet krijg je maar 2.5V op je ingang. En dat is ook weer kritisch.

EDIT:

@TS,

Net even het adapter printje gevreesd.

Als je haar maar goed zit, GROETEN LAMBIEK.

Op 12 september 2020 10:29:54 schreef SparkyGSX:
@TS: de 12V vanaf je accu is geen "schone" 12V, het is verstandig om een beetje beveiliging te voorzien, om de ergste rommel buiten de deur te houden. Nu is de load dump in ISO 7637-2 en ISO 16750-2 wel erg ruig; 80V op een 12V systeem (dat is wanneer de dynamo de accu stevig aan het laden is, en de verbinding naar die accu verbroken wordt).

Zo'n voeding als Lambiek voorstelt is prima, als je daar even een seriediode voor zet, met een bufferelco met keramische of MKP parallel, en als je het goed wilt doen nog een TVS voor de korte en hoge pieken.

We gaan die ingang inderdaad "opschonen" om eventuele pieken te voorkomen. Nu ben ik daar zelf niet zo bang voor want de 12V punten zijn in de tegenwoordige trekkers ook gestabiliseerd. Een moderne trekker doet niet veel onder voor een moderne auto wat dat betreft.

Ik heb nog wel even een verzoek vwb de code. Op de analoge outputs zitten nu LED's ter controle van de programma status. Maar deze zal ik niet gaan gebruiken omdat het mij toch niet veel zal zeggen als er zo'n ledje brandt. In plaats daarvan zou ik liever de 5 LED's als output hebben die de LED's van de laserontvanger kopieren omdat deze niet meer zichtbaar zullen zijn. Is dit mogelijk?

Op 12 september 2020 10:48:45 schreef Lambiek:Ik zie daar toch liever nog een pull-down van 10K, maar als je dat doet krijg je maar 2.5V op je ingang. En dat is ook weer kritisch

Niet als je de pull-down voor de serieweerstand zet.

@TS: Wil je dat ze mee knipperen? Wat ze nu doen, is de status van de ingangen volgen na het filter; dus het enige verschil is dat ze niet knipperen, maar blijven branden in de uit-periode van de LEDs van de ontvanger. Alleen A5, die aangeeft of de ingang stabiel is, zou je dan weg kunnen laten. Uitgang D1 geeft aan of de automatische mode actief is, ik neem aan dat je die gewoon wilt behouden.

Als je de regel

code:

digitalWrite( A0 + Index, !InputCounters[ Index ] );

vervangt door

code:

digitalWrite( A0 + Index, !ReadInputs & ( 1 << Index ) );

volgen ze de ingangen; als je de LEDs van de uitgang naar de ground zet, in plaats van vanaf de voeding naar de uitgang (sourcen vs. sinken) moet je het uitroepteken weghalen.

[Bericht gewijzigd door SparkyGSX op 16 september 2020 21:13:23 (53%)]

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

Op 16 september 2020 19:16:06 schreef SparkyGSX:

@TS: Wil je dat ze mee knipperen?

Ik ben persoonlijk meer voorstander van gewoon branden ipv knipperen. Eigenlijk gewoon zoals we de outputs voor de relais ook aansturen.

Echt precies terwijl ik de code schrijf :-p

Dan doen ze zonder wijzigingen gewoon wat je wilt, in mijn beleving.

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

Aha, dan heb ik deze zin van jou niet goed begrepen.

Op 7 september 2020 20:39:55 schreef SparkyGSX:

De analoge pinnen worden niet analoog gebruikt, maar voor 6 LEDs die de interne status weergeven; A0 t/m A4 geven de status van de ingangen na het filter, terwijl A5 weergeeft of de status stabiel is bevonden. Elk van deze pinnen moet daarvoor een LED krijgen met een weerstand in serie, van de uitgang naar de ground voeding.

Maar nu ik hem nog eens goed lees begrijp ik dat A0 t/m A4 gewoon al de output weergeeft die naar de relais wordt gestuurd?
Had ik ze toch maar even aangesloten dan..... :S

Nee, die geven de status van de ingangen, na het filter dat het knipperen moet onderdrukken. Als je LEDs wil die de status weergeven van de relais, waarom zet je die LEDs dan niet gewoon parallel met de relais? Elke LED even een weerstandje geven, natuurlijk.

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

Ja dat kan natuurlijk ook. Maar zoals jij hem omschrijft is het beter. Wat is eigenlijk de reden dat ze een weerstand naar de voeding krijgen ipv naar de GND?

Vaak zijn de eigenschappen van I/O pinnen beter voor sinken (schakelen naar ground) dan voor sourcen (schakelen naar voeding). Daarbij trek je, als je naar de ground schakelt, geen stroom uit de ontkoppelcondensators van de microcontroller, en die zijn bij Arduino's toch al wat beperkt. Die ontkoppelcondensators blijven op die manier helemaal beschikbaar voor het voeden van de interne circuits van de microcontroller.

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

@ Sparky,

Ik ben zojuist bezig geweest met de code aan te passen zodat de poorten overeenkomen met hoe ik ze uiteindelijk aan wil sluiten. Ook heb ik de poorten namen gegeven zodat ik de omnummering enkel bovenin de code hoefde te doen. Zie onder de volledige code.
Ik vraag me nu alleen af of ik iets vergeten ben of iets niet goed gedaan heb want de relais schakelen nu niet goed mee, ze schakelen soms wel en soms niet. Zou jij hier eens naar kunnen kijken en evt zeggen wat ik verkeerd heb gedaan?

Tot slot heb ik in onderstaande regel de ! voor Inputcounters verwijderd omdat ik een hoge output wil hebben op de poorten voor de LEDs omdat ik deze via een ULN2803 schakel. Heb ik dit goed gedaan?

code:


    digitalWrite( led_top + Index, InputCounters[ Index ] );

Hier de volledige code:

code:


#define MAX_INTERVAL 150 // 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;

int input_pushbutton = 1; // pushbutton for automatic mode
int input_joy_up = 2; // joystick UP
int input_joy_down = 3; // joystick DOWN
int input_top = 4; // input top LED
int input_up = 5;
int input_mid = 6;
int input_down = 7;
int input_bottom = 8; // input bottom LED
int led_error = 9; // Error output
int led_auto = 10;  // LED for automatic mode
int output_up = 11; // move UP output
int output_down = 12; // move DOWN output
int output_slow = 13; // move SLOW output
int led_top = A0; // Indication lED move UP
int led_up = A1;
int led_mid = A2;
int led_down = A3;
int led_bottom = A4; // Indication lED move DOWN
int led_stable = A5; // LED for stable status


void setup()
{
  // pin 0 unused; causes problems when loading new software
  pinMode( input_pushbutton, INPUT ); // pushbutton for automatic mode
  pinMode( input_joy_up, INPUT ); // joystick UP
  pinMode( input_joy_down, INPUT ); // joystick DOWN
  pinMode( input_top, INPUT ); // input top LED
  pinMode( input_up, INPUT );
  pinMode( input_mid, INPUT );
  pinMode( input_down, INPUT );
  pinMode( input_bottom, INPUT ); // input bottom LED
  pinMode( led_error, OUTPUT ); // Error output
  pinMode( led_auto, OUTPUT ); // LED for automatic mode  
  pinMode( output_up, OUTPUT ); // move UP output
  pinMode( output_down, OUTPUT ); // move DOWN output
  pinMode( output_slow, OUTPUT ); // move FAST output (low=fast)
  pinMode( led_top, OUTPUT ); // Debugging status LEDs
  pinMode( led_up, OUTPUT );
  pinMode( led_mid, OUTPUT );
  pinMode( led_down, OUTPUT );
  pinMode( led_bottom, OUTPUT );
  pinMode( led_stable, OUTPUT );
}

void loop()
{
  unsigned char Index;
  
  FilteredInputs = 0;
  ReadInputs = ( digitalRead( input_top ) ) | ( digitalRead( input_up ) << 1 ) | ( digitalRead( input_mid ) << 2 ) | ( digitalRead( input_down ) << 3 ) | ( digitalRead( input_bottom ) << 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( led_top + 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( led_stable, !StabilityCount );

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

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

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

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

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

Alvast bedankt weer!

Aangenomen dat de pinnummers kloppen met de werkelijkheid, zie ik niet direct wat er mis zou zijn. Ik zie wel dat je MAX_INTERVAL hebt verlaagd van 200 naar 150; als de LEDs bij het knipperen langer uit zijn dan dat, werkt het niet meer. Waarom heb je dat gedaan, en werkt het wel als je dat terug zet?

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

Op 26 september 2020 22:42:46 schreef SparkyGSX:
Ik zie wel dat je MAX_INTERVAL hebt verlaagd van 200 naar 150; als de LEDs bij het knipperen langer uit zijn dan dat, werkt het niet meer. Waarom heb je dat gedaan, en werkt het wel als je dat terug zet?

Aha dat is wel een goeie. In mijn testopstelling heb ik niet meer de ontvanger zelf als input maar een los knipperend LEDje, deze zal ik niet snel genoeg hebben laten knipperen denk ik. Morgen even proberen.
Die 150ms werkt trouwens prima op de ontvanger, ik heb hier een beetje mee zitten spelen om te kijken hoe ver ik kon gaan. Vandaar de veranderde waarde.

Ok, dat is opgelost. De Led stond idd te langzaam ingesteld.
Ik heb nog wel een andere vraag. Zodra ik de fototransistors belicht geven de output Leds vrijwel direct een signaal maar de relais schakelen pas na +/- 2 seconden. Is hier een reden voor en kan ik dit nog finetunen? Ik kan die delay namelijk niet in de code terug vinden.

EDIT:
Inmiddels ben ik erachter denk ik, het komt omdat ik hem handmatig van de ene transistor naar de volgende beweeg en als ik dit niet snel genoeg doe zal hij dit beschouwen als "lost signal". Als ik heel snel beweeg gaat dit wel goed. Dit zal ook de praktijk zijn want op de ontvanger zit er vrijwel geen tijd tussen de ene led en de andere.

[Bericht gewijzigd door BartL op 27 september 2020 17:30:10 (34%)]

@Sparky,

Ik heb vandaag eindelijk de mogelijkheid gehad om het geheel op de machine te testen. Het systeem werkt nog niet helemaal naar behoren vanwege het simpele feit dat ik iets gemist heb bij het opstellen van de specs. Het blijkt namelijk dat wanneer de laser op grotere afstand staat het mogelijk is 2 secties tegelijk te laten branden. Dus bijvoorbeeld neutraal en 1 daarboven. In de code is dit nu zo geprogrammeerd dat hij dan niets doet maar dit zou dus aangepast moeten worden. Eigenlijk moet hij altijd reageren behalve als de onderste en de bovenste tegelijk knipperen (geen signaal). Zou je dit nog aan kunnen passen in de code?

Alvast bedankt weer!!

Voor de volledigheid, dit is de code die ik nu gebruik.

code:


#define MAX_INTERVAL 150 // 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;

int input_pushbutton = 1; // pushbutton for automatic mode
int input_joy_up = 2; // joystick UP
int input_joy_down = 3; // joystick DOWN
int input_top = 4; // input top LED
int input_up = 5; // input 2nd LED from top
int input_mid = 6; // input neutral LED
int input_down = 7; // input 2nd LED from bottom
int input_bottom = 8; // input bottom LED
int led_error = 9; // Error output
int led_auto = 10;  // LED for automatic mode
int output_up = 11; // move UP output
int output_down = 12; // move DOWN output
int output_slow = 13; // move SLOW output
int led_top = A0; // Indication lED move UP
int led_up = A1;
int led_mid = A2;
int led_down = A3;
int led_bottom = A4; // Indication lED move DOWN
int led_stable = A5; // LED for stable status


void setup()
{
  // pin 0 unused; causes problems when loading new software
  pinMode( input_pushbutton, INPUT ); // pushbutton for automatic mode
  pinMode( input_joy_up, INPUT ); // joystick UP
  pinMode( input_joy_down, INPUT ); // joystick DOWN
  pinMode( input_top, INPUT ); // input top LED
  pinMode( input_up, INPUT );
  pinMode( input_mid, INPUT );
  pinMode( input_down, INPUT );
  pinMode( input_bottom, INPUT ); // input bottom LED
  pinMode( led_error, OUTPUT ); // Error output
  pinMode( led_auto, OUTPUT ); // LED for automatic mode  
  pinMode( output_up, OUTPUT ); // move UP output
  pinMode( output_down, OUTPUT ); // move DOWN output
  pinMode( output_slow, OUTPUT ); // move FAST output (low=fast)
  pinMode( led_top, OUTPUT ); // Debugging status LEDs
  pinMode( led_up, OUTPUT );
  pinMode( led_mid, OUTPUT );
  pinMode( led_down, OUTPUT );
  pinMode( led_bottom, OUTPUT );
  pinMode( led_stable, OUTPUT );
}

void loop()
{

  unsigned char Index;
  
  FilteredInputs = 0;
  ReadInputs = ( digitalRead( input_top ) ) | ( digitalRead( input_up ) << 1 ) | ( digitalRead( input_mid ) << 2 ) | ( digitalRead( input_down ) << 3 ) | ( digitalRead( input_bottom ) << 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( led_top + 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( led_stable, !StabilityCount );

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

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

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

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

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

}
[\Code]

Dat kan, maar dan kun je ook zelf aanpassen; het enige wat daarvoor moet gebeuren, is de Actions tabel uitbreiden. De bovenste ingang heeft index 1, de tweede van boven 2, en als allebei aan zijn wordt dat 3; op die plaats staat nu "DO_NOTHING", dus daar kun je "MOVE_UP" of "MOVE_UPFAST" neerzetten. Hetzelfde geldt voor neutraal + omhoog op plaats 2 + 4 = 6, neutraal + omlaag op 4 + 8 = 12, en de onderste 2 LEDs op 8 + 16 = 24.

Dit is wel aangenomen dat beide LEDs echt aan zijn, en niet heel hard heen- en weer staan te knipperen; in dat laatste geval zou er extra hardware of software nodig zijn.

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

Aha, dan snap ik nu (eindelijk) waar die regels voor dienen.
Dit heb ik net getest en dat werkt inderdaad. Nu loop ik alleen tegen het volgende probleem aan. Doordat er wat vering in de machine zit (waarschijnlijk deels omdat ik hem onbelast stationair test) schiet hij nu steeds de neutrale stand voorbij waardoor hij blijft bijsturen. Dit kan ik verhelpen door de oliestroom nog verder te reduceren maar dan wordt de gehele machine te langzaam om er nog goed mee te kunnen werken. Misschien zou ik dit op kunnen lossen door index 6 en 12 weer op DO_NOTHING te zetten. Maar daarmee accepteer ik eigenlijk ook tegelijk een groter bereik als neutrale stand. Als er dus mogelijkheden zijn om dit anders op te lossen...

Eh, tja met de beschikbare informatie van de sensoren zijn de mogelijkheden een beetje beperkt; het enige wat ik zo direct kan bedenken is een extra ventiel toevoegen om een paar seconden nadat door de neutraal bent gegaan een lagere snelheid aan te houden.

Eigenlijk heb je dat een redelijk fundamenteel probleem; blijkbaar blijft het ding nog even bewegen nadat het ventiel gesloten is, klopt dat? Komt dat door de rek in de leidingen, of is er iets anders dat veert en nog even door blijft drukken?

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

De machine deint inderdaad een beetje. Dit komt bijvoorbeeld door het veren van de lange trekdissel die eraan zit en door het veren van de wielen waar de machine op rijdt.
Nog een ventiel erbij zie ik niet zo zitten eigenlijk dan wordt het allemaal nogal complex.
Even simpel gedacht;
Zou het niet mogelijk zijn om index 6 en 12 op DO_NOTHING terug te zetten om ervoor te zorgen dat het neutraal bereik (tijdelijk) iets vergroot wordt. Daarna vervolgens het ventiel nog X seconden aansturen wanneer hij Y seconden in die stand (6 of 12) blijft staan?
Met die timers kan ik dan wat spelen totdat hij goed werkt.

Dat zou wel kunnen, ik ga even nadenken over hoe dat er enigszins fatsoenlijk aan toegevoegd kan worden.

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

Even een update.

Nu ik 6 en 12 op DO_nothing heb gezet kan ik hem wel met acceptabele snelheid laten werken. Hoe dit uiteindelijk in het werk zal reageren is even afwachten. Wanneer er een paar kuub grond voor de schuif ligt zal hij anders reageren dan zoals nu zonder belasting op het beton.
Ik moet nog een paar dingen hydraulisch aanpassen en wanneer dit is gebeurt zal ik laten weten of het nog nodig is de Code eventueel aan te passen.

@Sparky,

Ik heb het systeem nog wat aangepast en hij begint nu redelijk goed te werken.
Eigenlijk heb ik (voor nu) nog 2 puntjes die ik graag aangepast zou willen hebben.

1. De klep die bediend wordt om hem langzaam te laten bewegen zou in de neutraal stand geactiveerd moeten blijven of anders later pas uit moeten schakelen. Dit omdat ik het systeem niet met een 3/2klep maar met een 2/2klep heb uitgevoegd met de smoring er als by-pass omheen. Dit werkt prima maar bij het naderen van de neutraalstand (2/2 klep dicht) wordt er druk opgebouwd tegen het smoorventiel. Wanneer de neutraalstand dan bereikt is en de klep weer open gaat schokt de machine nogal omdat deze druk dan ineens afgelaten wordt.

2. In de praktijk blijkt het beter te zijn om de machine toch te laten zakken of heffen in de "eruit gelopen" stand boven- of onderin. Als dit eventueel pulserend gaat ivm de afwijkende knipper frequentie is niet zo erg.

Hieronder de actuele code.

code:


#define MAX_INTERVAL 150 // 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; Every single input except for the middle input will result in movement.
// An input in combination with the input next to it wil also result in movement. All other combinations means DO_NOTHING.
// 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. 
// The movement combinations are: 3(up fast + up slow (1+2)), 6(up slow + neutral (2+4)), 12(neutral + down slow (4+8)) and 24(up slow + up fast (8+16)).
// Note the array index starts at 0
const unsigned char Actions[ 32 ] = 
  { DO_NOTHING, MOVE_UPFAST, MOVE_UP, MOVE_UP, 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
    MOVE_DOWN, 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;

int input_pushbutton = 1; // pushbutton for automatic mode
int input_joy_up = 2; // joystick UP
int input_joy_down = 3; // joystick DOWN
int input_top = 4; // input top LED
int input_up = 5; // input 2nd LED from top
int input_mid = 6; // input neutral LED
int input_down = 7; // input 2nd LED from bottom
int input_bottom = 8; // input bottom LED
int led_error = 9; // Error output
int led_auto = 10;  // LED for automatic mode
int output_up = 11; // move UP output
int output_down = 12; // move DOWN output
int output_slow = 13; // move SLOW output
int led_top = A0; // Indication lED move UP
int led_up = A1;
int led_mid = A2;
int led_down = A3;
int led_bottom = A4; // Indication lED move DOWN
int led_stable = A5; // LED for stable status


void setup()
{
  // pin 0 unused; causes problems when loading new software
  pinMode( input_pushbutton, INPUT ); // pushbutton for automatic mode
  pinMode( input_joy_up, INPUT ); // joystick UP
  pinMode( input_joy_down, INPUT ); // joystick DOWN
  pinMode( input_top, INPUT ); // input top LED
  pinMode( input_up, INPUT );
  pinMode( input_mid, INPUT );
  pinMode( input_down, INPUT );
  pinMode( input_bottom, INPUT ); // input bottom LED
  pinMode( led_error, OUTPUT ); // Error output
  pinMode( led_auto, OUTPUT ); // LED for automatic mode  
  pinMode( output_up, OUTPUT ); // move UP output
  pinMode( output_down, OUTPUT ); // move DOWN output
  pinMode( output_slow, OUTPUT ); // move FAST output (low=fast)
  pinMode( led_top, OUTPUT ); // Debugging status LEDs
  pinMode( led_up, OUTPUT );
  pinMode( led_mid, OUTPUT );
  pinMode( led_down, OUTPUT );
  pinMode( led_bottom, OUTPUT );
  pinMode( led_stable, OUTPUT );
}

void loop()
{

  unsigned char Index;
  
  FilteredInputs = 0;
  ReadInputs = ( digitalRead( input_top ) ) | ( digitalRead( input_up ) << 1 ) | ( digitalRead( input_mid ) << 2 ) | ( digitalRead( input_down ) << 3 ) | ( digitalRead( input_bottom ) << 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( led_top + 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( led_stable, !StabilityCount );

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

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

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

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

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

}