Section control by button

At my level , here is a simpler piece of code than what you suggest to me. It works but is not ideal because of the delay (), but is blocking the code for 10ms for each section a problem?

if ((bitRead (relayLo, 0) == 1) & (section1 == 0)) {
  bitClear (PORTD, 5); // Digital Pin 5 to open section relay
  section1 = 1;
  delay (10);
  }
else if ((bitRead (relayLo, 0) == 0) & (section1 == 1)) {
  bitClear (PORTC, 2); // A2 (16)  to close section relay
  section1 = 0;
  delay (10);
  }
else {
  bitSet (PORTD, 5);
  bitSet (PORTC, 2);
  }

Just that if you drive 20 km/h every 10 ms is 5cm so if you have 16 sections and need to change them all (headland?) you drive 75cm before all sections are changed

What happens if you press one of your buttons, and continue pressing it. Like if a relay was always on?

@DanielP there are 8 sections (16 relays, 8 to turn on, 8 to turn off), so 40cm … which is pretty good for spraying.

@Larsvest
it works, but will the teejet switch box enjoy working like this for a long time? I don t know .

Here is an interesting approach from @Math which corresponds if I understood correctly to what Brian suggested to me.

It’s in French .

I maybe wrong but If your manual switchbox is just input for a microcontroller, why add relays? try sending pulse parallel to switches direct from arduino. Best if you can squeeze it inside your controller box for common gnd.
Then send digitalwrite for AOG to emulate switch and digitalread rest of time to record any setting from the manual switches.
I would not use delay when writing, just count as Brian says, and use debounce in a isr when reading.

Hi
I agree, I abandoned the solution with delay (). The solution chosen will most likely be that proposed by @math. Counter and state detection.
For relays, When I have more time, I will test my switchbox.
The button simulation is solved in the arduino. Now I need to see what will be the best solution for the connection to the switchbox.
What about feedback from the switchbox to nano to AOG? Because if I spray without using AOG (this sometimes happens on a small strip) AOG needs to know this so as not to spray there a second time.

Hello,

Here is the code for special Tooki need, proposed in the french topic: Coupure de tronçons - #17 by Math.
This is the final version, tested and debbug by Tooki.

The only different between code below and the one on the french topic is the comments that I have translated in English.
I thinks for adanvanced user, the comments aren’t necessery to understand what it does (i’m not an advanced Arduino user). But in order to make it understanble by everyone (if someone has the same needs has Tooki), I translate and try to make the comments as clear possible.

Mainly, what the code does is that it detect a rising edge or falling edge on the bit 0 of the byte relayLo and generate a pulse on the digital pin 5 or 13 depending on the edge.

This is an example with the following hypothesis:

  • When AOG driving the section piloted by the bit 0 of the byte relayLo:
    • A pulse must be generated (simulates pressing a physical button) on the relay connected to the Digital pin 5, when AOG controls the section from 0 to 1
    • A pulse must be generated on the relay connected to the Digital pin 13 when AOG controls the section from 1 to 0
    • The pulse shall have a duration of 5 seconds

As suggested by Brian, I use a counter, based on the fact that the void SetRelays(void) is call every 200ms by the main loop. The the pulse can be ajusted by step of 200ms. It was easier to proceed like this rather than reuse the millis() fuction. And I think for driving a relay that simulate a physical button pressing, ~200ms time sample precision is enough.

The code is for one section. It must be copied and adapted for the other sections to be controlled: other bits of the relayLo byte to read and adapt the outputs to be controlled accordingly.
Only the global variable pulseCounter does not need to be duplicated.

Variables to declare at the start of the program, before the “void setup ()” loop:

// Parameters for pulse generator on relay outputs
#define pulseCounter 5 // Compteur qui défini le temps du pulse par pas de 200ms (ici 5*200ms = 1s)
boolean bit0Status, bit0MemoryState = 0; // Counter which defines the pulse time in 200ms steps (here 5 * 200ms = 1s)
char bit0Counter = 0; // A counter to count the activation time of the output (s) controlled by bit 0 of the byte relayLo

Changes to the void function “SetRelays (void)”:

void SetRelays(void) {

  bit0Status = bitRead(relayLo,0); // Reading of the state of bit 0 of the relayLo byte and storage in the bit0Status variable

  if (( bit0Status != bit0MemoryState) && (bit0Status == 1)) // If the bit0Status is different from its memory state & the state is 1, it means that there was a change from 0 to 1 by AOG on bit 0 of the byte relayLo
  {
    /*Description of the following if else:
     * If bit0Counter is less than 5, the SetRelays function has been called less than 5 times since AOG changed the state of bit 0 of the byte relayLo
     * If the result is greater, it means that the function has been called more than 5 times
     * The main loop that calls the SetRelays function is executed every 200ms (see the start of the "void loop ()" with the "currentTime" and the "if" on the "currentTime")
     * So to activate the output during 1S, the setRelays function must be called 5 times
     * This logic will enable the output which controls the relay with a pulse of 1s duration when there is a section command from AGO
     * To adjust the activation time of the output, adjust the counter (pulseCounter) which allows adjustment in 200ms steps
     */
    if (bit0Counter <= pulseCounter)
    {
      bitSet(PORTD, 5); // Digital pin 5 activation
      bit0Counter++; // We increment by 1 bit0Counter
    }
    else
    {
      bitClear(PORD, 5); // Digital pin 5 deactivation
      bit0MemoryState = bit0Status; // We store the state of bit 0 provided by AOG so as not to activate the output until we have had a change of state of bit 0 from AOG
      bit0Counter == 0; // We reset the counter to 0 for the next move
    }
  }
  if (( bit0Status != bit0MemoryState) && (bit0Status == 0)) // If the bit0Status is different from its memory state & the state is 0, it means that there was a change from 1 to 0 by AOG on bit 0 of the byte relayLo
    if (bit0Counter <= pulseCounter) // Loop if else same as above, but on another relay, for the change of bit 0 byte relayLo from 1 to 0 by AOG
    {
      bitSet(PORTB, 5); // Digital pin 13 activation
      bit0Counter++; // We increment by 1 bit0Counter
    }
    else
    {
      bitClear(PORDB, 5); // Digital pin 13 deactivation
      bit0MemoryState = bit0Status; // We store the state of bit 0 provided by AOG so as not to activate the output until we have had a change of state of bit 0 from AOG
      bit0Counter == 0; // We reset the counter to 0 for the next move
    }
   }
}

Math

1 Like

Could someone explain to me why the loop in machine_usb.ino is 5hz?
Could I speed it up?
If the change of state is faster than 200ms, as I could see in sim during a tight turn, a relay can stay on when it should be off.

It could be faster yes, change the 200 to 100. But, will 100ms really make much difference?

Hello
One little additionnal question :
With a sprayer (7 sections for me) working manually, is it possible
to indicate which sections are on or off to AOG ?

On my section module, I receive correctly the values from AOG (PGN 7FFA) but when returning the
real value (PGN 7FF9) the information do not return in AOG.
I’ve tried with UDP and serial port, same)
Do this feature works, Is there a specific configuration in AOG (tool/switches) ?
Thanks for the help,
francois

Send PGN 32761 to AOG for section control.

PGN32761

The SecOn Hi and SecOn Lo bytes will tell AOG which sections are on.