• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Modelarski sterownik silnika DC na Atmega8 według projektu AVT
#11
Biblioteka nie jest potrzebna do przycisku, odpowiednio napisany kod obsługi tak, bo inaczej będzie działać kulawo.
W przykładach Bascom miałem debounce zrobiony na Waitms 50? Ta płytka z Atmegą 644 kosztowała prawie 200 w 2008r, i przykłady nie działały, wylądowała po zakupie na wiele lat w szufladzie, bo były dla Atmaga32 teraz z Atmega32 widzę za 400 (książka obowiązkowa za kolejne 150). Tyle że niedostępne i tak, bo procki znikły.
W Arduino kupisz 10 płytek MEGA w tej cenie (czy kupiłbyś, w tym roku cenom odwaliło, a procki zniknęły), albo 50 NANO.
Bibliotek jest o wyboru dla samego przycisku kilkaset, rozpoznają kliknięcie, przytrzymanie, dubleklick - nie trzeba wymyślać koła od nowa bez żadnego delay/_delay_ms czy Waitms.
Zaletą Arduino jest to, że te biblioteki są, jest ich masa do wszystkiego, są za darmo.
Programy w kursach mogą Cię nie interesować, klepie się je przez kwartał po to by wywalić z głowy instrukcje C czy basic, nauczyć się tych z Arduino. Jak z nauką czytania, zaczynasz sklejać literki, potem rozumieć słowa, układać zdania.
Trzeba to przejść ten początek nawet jeśli nie widać sensu.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#12
Mam jedną płýtke Nano i drugą z wgranym Marlinem do drukark 3d a która dojrzewa no i jeszcze ten model z atmega8 ( mam kilka procesorów) a muszę się pochwalić ze udało mi się napisać szkic który czyta wartość impulsów ale jeszcze nie wymyśliłem jak przejsc na sterowanie mostkiem H choć mam szkic na dwa silniki na mostkach.
 
Odpowiedź
#13
To pochwal się. W programie trzeba robić wszystko tak często jak to konieczne, ale nie częściej, a po drugie nie zatrzymywać go delay, tak by zawsze na wszystko inne było tyle czasu ile się da.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#14
A proszę bardzo
Kod:
[code]
/* test z monitorowaniem wartosci kanału na arduino nano
*/
//definicje kanalow
#define CH1 2
//zmienne
int ch1Value;
//czytaj kanał 
int readChannel(int channelInput, int minLimit, int maxLimit, int defaultValue){
  int ch = pulseIn(channelInput, HIGH, 30000);
  if (ch < 100) return defaultValue;
  return map(ch, 1000, 2000, minLimit, maxLimit);

}
//
bool readSwitch(byte channelInput, bool defaultValue){
  int intDefaultValue = (defaultValue)? 100: 0;
  int ch = readChannel(channelInput, 0, 100, intDefaultValue);
  return (ch > 50);
}
  //***********************************************************************
  void setup(){
  // Set up serial monitor
  Serial.begin(115200);
  pinMode(CH1, INPUT);
  }
//*************************************************************************
void loop() {

  ch1Value = readChannel(CH1, -100, 100, -100);
  Serial.print("Ch1: ");
  Serial.print(ch1Value);
 
 
  delay(500);
  }
gdyby było to jeszcze ładnie widać było w monitorze ale działa to już coś
A tu jeszcze inny przykład według autora który ma służyć do kalibracji i pokazuje wartości od 1000 do 2000 ale nie wiem jak przenieść te wartości i sterować mostek H
Kod:
//geeky singh 14th dec 2015 for instructables.com

#define SRC_NEUTRAL 1500
#define SRC_MAX 2000
#define SRC_MIN 1000
//#define TRC_NEUTRAL 1500
//#define TRC_MAX 2000
//#define TRC_MIN 1000
#define RC_DEADBAND 50
#define ERROR_center 50
#define pERROR 100 

uint16_t unSteeringMin = SRC_MIN + pERROR;
uint16_t unSteeringMax = SRC_MAX - pERROR;
uint16_t unSteeringCenter = SRC_NEUTRAL;

//uint16_t unThrottleMin = TRC_MIN + pERROR;
//uint16_t unThrottleMax = TRC_MAX - pERROR;
//uint16_t unThrottleCenter = TRC_NEUTRAL;

#define PWM_MIN 0
#define PWM_MAX 255

#define GEAR_NONE 1
#define GEAR_IDLE 1
#define GEAR_FULL 2

#define PWM_SPEED_LEFT 10
#define PWM_SPEED_RIGHT 11
#define LEFT1 5
#define LEFT2 6
#define RIGHT1 7
#define RIGHT2 8

#define PROGRAM_PIN 9

// Assign your channel in pins
#define THROTTLE_IN_PIN 2
#define STEERING_IN_PIN 3

// These bit flags are set in bUpdateFlagsShared to indicate which
// channels have new signals
#define THROTTLE_FLAG 1
//#define STEERING_FLAG 2

// holds the update flags defined above
volatile uint8_t bUpdateFlagsShared;

// shared variables are updated by the ISR and read by loop.
// In loop we immediatley take local copies so that the ISR can keep ownership of the
// shared ones. To access these in loop
// we first turn interrupts off with noInterrupts
// we take a copy to use in loop and the turn interrupts back on
// as quickly as possible, this ensures that we are always able to receive new signals
volatile uint16_t unThrottleInShared;
volatile uint16_t unSteeringInShared;

// These are used to record the rising edge of a pulse in the calcInput functions
// They do not need to be volatile as they are only used in the ISR. If we wanted
// to refer to these in loop and the ISR then they would need to be declared volatile
uint32_t ulThrottleStart;
uint32_t ulSteeringStart;

uint8_t gThrottle = 0;
uint8_t gGear = GEAR_NONE;
uint8_t gOldGear = GEAR_NONE;

#define DIRECTION_STOP 0
#define DIRECTION_FORWARD 1
#define DIRECTION_REVERSE 2
#define DIRECTION_ROTATE_RIGHT 3
#define DIRECTION_ROTATE_LEFT 4

uint8_t gThrottleDirection = DIRECTION_STOP;
uint8_t gDirection = DIRECTION_STOP;
uint8_t gOldDirection = DIRECTION_STOP;

#define IDLE_MAX 50

#define MODE_RUN 0


uint8_t gMode = MODE_RUN;

unsigned long pulse_time  ;

void setup()
{
  Serial.begin(115200);

  Serial.println("hello");

  attachInterrupt(0 /* INT0 = THROTTLE_IN_PIN */,calcThrottle,CHANGE);
  //attachInterrupt(1 /* INT1 = STEERING_IN_PIN */,calcSteering,CHANGE);

  pinMode(PWM_SPEED_LEFT,OUTPUT);
  pinMode(PWM_SPEED_RIGHT,OUTPUT);
  pinMode(LEFT1,OUTPUT);
  pinMode(LEFT2,OUTPUT);
  pinMode(RIGHT1,OUTPUT);
  pinMode(RIGHT2,OUTPUT);
   pinMode(12,OUTPUT);
   pulse_time =millis() ;
  pinMode(PROGRAM_PIN,INPUT);

 
}

void loop()
{
  // create local variables to hold a local copies of the channel inputs
  // these are declared static so that thier values will be retained
  // between calls to loop.
  static uint16_t unThrottleIn;
  static uint16_t unSteeringIn;
  // local copy of update flags
  static uint8_t bUpdateFlags;
// fail_safe();
  // check shared update flags to see if any channels have a new signal
  if(bUpdateFlagsShared)
  {
    noInterrupts(); // turn interrupts off quickly while we take local copies of the shared variables
     pulse_time =millis() ;
      // take a local copy of which channels were updated in case we need to use this in the rest of loop
    bUpdateFlags = bUpdateFlagsShared;

    // in the current code, the shared values are always populated
    // so we could copy them without testing the flags
    // however in the future this could change, so lets
    // only copy when the flags tell us we can.

    if(bUpdateFlags & THROTTLE_FLAG)
    {
      unThrottleIn = unThrottleInShared;
    }

  //  if(bUpdateFlags & STEERING_FLAG)
    {
      unSteeringIn = unSteeringInShared;
    }

    // clear shared copy of updated flags as we have already taken the updates
    // we still have a local copy if we need to use it in bUpdateFlags
    bUpdateFlagsShared = 0;

    interrupts(); // we have local copies of the inputs, so now we can turn interrupts back on
    // as soon as interrupts are back on, we can no longer use the shared copies, the interrupt
    // service routines own these and could update them at any time. During the update, the
    // shared copies may contain junk. Luckily we have our local copies to work with :-)
  }


  // do any processing from here onwards
  // only use the local values unAuxIn, unThrottleIn and unSteeringIn, the shared
  // variables unAuxInShared, unThrottleInShared, unSteeringInShared are always owned by
  // the interrupt routines and should not be used in loop
 
  if(gMode == MODE_RUN)
  {
    // we are checking to see if the channel value has changed, this is indicated
    // by the flags. For the simple pass through we don't really need this check,
    // but for a more complex project where a new signal requires significant processing
    // this allows us to only calculate new values when we have new inputs, rather than
    // on every cycle.
    if(bUpdateFlags & THROTTLE_FLAG)
    {
      // A good idea would be to check the before and after value,
      // if they are not equal we are receiving out of range signals
      // this could be an error, interference or a transmitter setting change
      // in any case its a good idea to at least flag it to the user somehow
//      unThrottleIn = constrain(unThrottleIn,unThrottleMin,unThrottleMax);
     
//      if(unThrottleIn > (unThrottleCenter + ERROR_center))
      {
     //   gThrottle = map(unThrottleIn,(unThrottleCenter + ERROR_center),unThrottleMax,PWM_MIN,PWM_MAX);
        gThrottleDirection = DIRECTION_FORWARD;
      }
//      else if (unThrottleIn < (unThrottleCenter - ERROR_center))
      {
   //     gThrottle = map(unThrottleIn,unThrottleMin,(unThrottleCenter- ERROR_center),PWM_MAX,PWM_MIN);
        gThrottleDirection = DIRECTION_REVERSE;
      }

     // else
      {
      gThrottleDirection =DIRECTION_STOP;
      gThrottle=0;
      }
 
      if(gThrottle < IDLE_MAX)
      {
        gGear = GEAR_IDLE;
      }
      else
      {
        gGear = GEAR_FULL;
      }
    }
 
  //  if(bUpdateFlags & STEERING_FLAG)
    {
      uint8_t throttleLeft = gThrottle;
      uint8_t throttleRight = gThrottle;
 
      gDirection = gThrottleDirection;
     
      // see previous comments regarding trapping out of range errors
      // this is left for the user to decide how to handle and flag
      unSteeringIn = constrain(unSteeringIn,unSteeringMin,unSteeringMax);
 
      // if idle spin on spot
      switch(gGear)
      {
      case GEAR_IDLE:
        if(unSteeringIn > (unSteeringCenter + RC_DEADBAND))
        {
          gDirection = DIRECTION_ROTATE_RIGHT;
          // use steering to set throttle
          throttleRight = throttleLeft = map(unSteeringIn,unSteeringCenter,unSteeringMax,PWM_MIN,PWM_MAX);
        }
        else if(unSteeringIn < (unSteeringCenter - RC_DEADBAND))
        {
          gDirection = DIRECTION_ROTATE_LEFT;
          // use steering to set throttle
          throttleRight = throttleLeft = map(unSteeringIn,unSteeringMin,unSteeringCenter,PWM_MAX,PWM_MIN);
        }
        break;
      // if not idle proportionally restrain inside track to turn vehicle around it
      case GEAR_FULL:
        if(unSteeringIn > (unSteeringCenter + RC_DEADBAND))
        {
          throttleLeft = map(unSteeringIn,unSteeringCenter,unSteeringMax,gThrottle,PWM_MIN);
        }
        else if(unSteeringIn < (unSteeringCenter - RC_DEADBAND))
        {
          throttleRight = map(unSteeringIn,unSteeringMin,unSteeringCenter,PWM_MIN,gThrottle);
        }
       
        break;
      }
      analogWrite(PWM_SPEED_LEFT,throttleLeft);
      analogWrite(PWM_SPEED_RIGHT,throttleRight);
    }
  }
 
  if((gDirection != gOldDirection) || (gGear != gOldGear))
  {
    gOldDirection = gDirection;
    gOldGear = gGear;

    digitalWrite(LEFT1,LOW);
    digitalWrite(LEFT2,LOW);
    digitalWrite(RIGHT1,LOW);
    digitalWrite(RIGHT2,LOW);

    switch(gDirection)
    {
    case DIRECTION_FORWARD:
      digitalWrite(LEFT1,LOW);
      digitalWrite(LEFT2,HIGH);
      digitalWrite(RIGHT1,LOW);
      digitalWrite(RIGHT2,HIGH);
      break;
    case DIRECTION_REVERSE:
      digitalWrite(LEFT1,HIGH);
      digitalWrite(LEFT2,LOW);
      digitalWrite(RIGHT1,HIGH);
      digitalWrite(RIGHT2,LOW);
      break;
    case DIRECTION_ROTATE_RIGHT:
      digitalWrite(LEFT1,HIGH);
      digitalWrite(LEFT2,LOW);
      digitalWrite(RIGHT1,LOW);
      digitalWrite(RIGHT2,HIGH);
      break;
    case DIRECTION_ROTATE_LEFT:
      digitalWrite(LEFT1,LOW);
      digitalWrite(LEFT2,HIGH);
      digitalWrite(RIGHT1,HIGH);
      digitalWrite(RIGHT2,LOW);
      break;
    case DIRECTION_STOP:
      digitalWrite(LEFT1,LOW);
      digitalWrite(LEFT2,LOW);
      digitalWrite(RIGHT1,LOW);
      digitalWrite(RIGHT2,LOW);
      break;
    }
  }

  bUpdateFlags = 0;
}


// simple interrupt service routine
void calcThrottle()
{
  // if the pin is high, its a rising edge of the signal pulse, so lets record its value
  if(digitalRead(THROTTLE_IN_PIN) == HIGH)
  {
    ulThrottleStart = micros();
  }
  else
  {
    // else it must be a falling edge, so lets get the time and subtract the time of the rising edge
    // this gives use the time between the rising and falling edges i.e. the pulse duration.
    unThrottleInShared = (uint16_t)(micros() - ulThrottleStart);
    // use set the throttle flag to indicate that a new throttle signal has been received
    bUpdateFlagsShared |= THROTTLE_FLAG;
  }
}

void calcSteering()
{
  if(digitalRead(STEERING_IN_PIN) == HIGH)
  {
    ulSteeringStart = micros();
  }
  else
  {
    unSteeringInShared = (uint16_t)(micros() - ulSteeringStart);
  //  bUpdateFlagsShared |= STEERING_FLAG;
  }
}
 
Odpowiedź
#15
No i teraz to samo tylko bez delay 500, bo to znaczy, że przez pół sekundy układ jest głuchy i ślepy, a faktycznie przez większość czasu działania programu, jeśli ta funkcja readChannel trwa z 10us, to tak z 99.99% czasu działania.
Naucz się używać millis(), jeślibyś tu dodał jakiś przycisk i digitalRead(), ta funkcja wykonuje się w czasie kilkudziesięciu us, a układ zostaje "wyłączony" na 500ms, kliknięcie przycisku powoduje drgania styków przez 30ms, czyli w ciągu 1s masz szansę, by to zauważyć jakieś 3%.
W historii moich postów jest wiele przykładów z użyciem millis, podstawowe działania matematyczne by zliczać upływający czas i na tej podstawie sterować czynnościami.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#16
Ale teraz o którym kodzie piszesz ? bo to są dwa rożne źródła ale zawsze maja dwa silniki i dwa kanały nawet pierwszy ma 6, nadal nie bardzo kumam o co w tym chodzi bo znalazłem np. bibliotekę silników, jakiś impulsów ale jak to połączyć w całość ? Arduino to zupełnie inna koncepcja pisania programów niż trochę mi znany Basom. Probowałem jeden z programów ten drugi z kalibracją ( to jest fragment do kalibrowania robota na 2 silnikach i sterowany dwoma kanałami przerobić na jedno kanałowy i kiepsko mi to idzie ( wcale nie idzie )
może rzuć okiem to coś mi podpowiesz.
Kod:
[quote]

[color=#7E7E7E]//geeky singh 14th dec 2015 for instructables.com[/color]

#define SRC_NEUTRAL 1500
#define SRC_MAX 2000
#define SRC_MIN 1000
[color=#7E7E7E]//#define TRC_NEUTRAL 1500[/color]
[color=#7E7E7E]//#define TRC_MAX 2000[/color]
[color=#7E7E7E]//#define TRC_MIN 1000[/color]
#define RC_DEADBAND 50
#define ERROR_center 50
#define pERROR 100  

uint16_t unSteeringMin = SRC_MIN + pERROR;
uint16_t unSteeringMax = SRC_MAX - pERROR;
uint16_t unSteeringCenter = SRC_NEUTRAL;

[color=#7E7E7E]//uint16_t unThrottleMin = TRC_MIN + pERROR;[/color]
[color=#7E7E7E]//uint16_t unThrottleMax = TRC_MAX - pERROR;[/color]
[color=#7E7E7E]//uint16_t unThrottleCenter = TRC_NEUTRAL;[/color]

#define PWM_MIN 0
#define PWM_MAX 255

#define GEAR_NONE 1
#define GEAR_IDLE 1
#define GEAR_FULL 2

#define PWM_SPEED_LEFT 10
#define PWM_SPEED_RIGHT 11
#define LEFT1 5
#define LEFT2 6
#define RIGHT1 7
#define RIGHT2 8

#define PROGRAM_PIN 9

[color=#7E7E7E]// Assign your channel in pins[/color]
#define THROTTLE_IN_PIN 2
#define STEERING_IN_PIN 3

[color=#7E7E7E]// These bit flags are set in bUpdateFlagsShared to indicate which[/color]
[color=#7E7E7E]// channels have new signals[/color]
#define THROTTLE_FLAG 1
[color=#7E7E7E]//#define STEERING_FLAG 2[/color]

[color=#7E7E7E]// holds the update flags defined above[/color]
volatile uint8_t bUpdateFlagsShared;

[color=#7E7E7E]// shared variables are updated by the ISR and read by loop.[/color]
[color=#7E7E7E]// In loop we immediatley take local copies so that the ISR can keep ownership of the[/color]
[color=#7E7E7E]// shared ones. To access these in loop[/color]
[color=#7E7E7E]// we first turn interrupts off with noInterrupts[/color]
[color=#7E7E7E]// we take a copy to use in loop and the turn interrupts back on[/color]
[color=#7E7E7E]// as quickly as possible, this ensures that we are always able to receive new signals[/color]
volatile uint16_t unThrottleInShared;
volatile uint16_t unSteeringInShared;

[color=#7E7E7E]// These are used to record the rising edge of a pulse in the calcInput functions[/color]
[color=#7E7E7E]// They do not need to be volatile as they are only used in the ISR. If we wanted[/color]
[color=#7E7E7E]// to refer to these in loop and the ISR then they would need to be declared volatile[/color]
uint32_t ulThrottleStart;
uint32_t ulSteeringStart;

uint8_t gThrottle = 0;
uint8_t gGear = GEAR_NONE;
uint8_t gOldGear = GEAR_NONE;

#define DIRECTION_STOP 0
#define DIRECTION_FORWARD 1
#define DIRECTION_REVERSE 2
#define DIRECTION_ROTATE_RIGHT 3
#define DIRECTION_ROTATE_LEFT 4

uint8_t gThrottleDirection = DIRECTION_STOP;
uint8_t gDirection = DIRECTION_STOP;
uint8_t gOldDirection = DIRECTION_STOP;

#define IDLE_MAX 50

#define MODE_RUN 0


uint8_t gMode = MODE_RUN;

[color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] pulse_time  ;

[color=#CC6600]void[/color] [color=#CC6600][b]setup[/b][/color]()
{
  [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]begin[/color](115200);

  [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color]([color=#006699]"hello"[/color]);

  [color=#CC6600]attachInterrupt[/color](0 [color=#7E7E7E]/* INT0 = THROTTLE_IN_PIN */[/color],calcThrottle,[color=#006699]CHANGE[/color]);
  [color=#7E7E7E]//attachInterrupt(1 /* INT1 = STEERING_IN_PIN */,calcSteering,CHANGE);[/color]

  [color=#CC6600]pinMode[/color](PWM_SPEED_LEFT,[color=#006699]OUTPUT[/color]);
  [color=#CC6600]pinMode[/color](PWM_SPEED_RIGHT,[color=#006699]OUTPUT[/color]);
  [color=#CC6600]pinMode[/color](LEFT1,[color=#006699]OUTPUT[/color]);
  [color=#CC6600]pinMode[/color](LEFT2,[color=#006699]OUTPUT[/color]);
  [color=#CC6600]pinMode[/color](RIGHT1,[color=#006699]OUTPUT[/color]);
  [color=#CC6600]pinMode[/color](RIGHT2,[color=#006699]OUTPUT[/color]);
   [color=#CC6600]pinMode[/color](12,[color=#006699]OUTPUT[/color]);
   pulse_time =[color=#CC6600]millis[/color]() ;
  [color=#CC6600]pinMode[/color](PROGRAM_PIN,[color=#006699]INPUT[/color]);

  
}

[color=#CC6600]void[/color] [color=#CC6600][b]loop[/b][/color]()
{
  [color=#7E7E7E]// create local variables to hold a local copies of the channel inputs[/color]
  [color=#7E7E7E]// these are declared static so that thier values will be retained[/color]
  [color=#7E7E7E]// between calls to loop.[/color]
  [color=#CC6600]static[/color] uint16_t unThrottleIn;
  [color=#CC6600]static[/color] uint16_t unSteeringIn;
  [color=#7E7E7E]// local copy of update flags[/color]
  [color=#CC6600]static[/color] uint8_t bUpdateFlags;
[color=#7E7E7E]// fail_safe();[/color]
  [color=#7E7E7E]// check shared update flags to see if any channels have a new signal[/color]
  [color=#CC6600]if[/color](bUpdateFlagsShared)
  {
    [color=#CC6600]noInterrupts[/color](); [color=#7E7E7E]// turn interrupts off quickly while we take local copies of the shared variables[/color]
     pulse_time =[color=#CC6600]millis[/color]() ;
      [color=#7E7E7E]// take a local copy of which channels were updated in case we need to use this in the rest of loop[/color]
    bUpdateFlags = bUpdateFlagsShared;

    [color=#7E7E7E]// in the current code, the shared values are always populated[/color]
    [color=#7E7E7E]// so we could copy them without testing the flags[/color]
    [color=#7E7E7E]// however in the future this could change, so lets[/color]
    [color=#7E7E7E]// only copy when the flags tell us we can.[/color]

    [color=#CC6600]if[/color](bUpdateFlags & THROTTLE_FLAG)
    {
      unThrottleIn = unThrottleInShared;
    }

  [color=#7E7E7E]//  if(bUpdateFlags & STEERING_FLAG)[/color]
    {
      unSteeringIn = unSteeringInShared;
    }

    [color=#7E7E7E]// clear shared copy of updated flags as we have already taken the updates[/color]
    [color=#7E7E7E]// we still have a local copy if we need to use it in bUpdateFlags[/color]
    bUpdateFlagsShared = 0;

    [color=#CC6600]interrupts[/color](); [color=#7E7E7E]// we have local copies of the inputs, so now we can turn interrupts back on[/color]
    [color=#7E7E7E]// as soon as interrupts are back on, we can no longer use the shared copies, the interrupt[/color]
    [color=#7E7E7E]// service routines own these and could update them at any time. During the update, the[/color]
    [color=#7E7E7E]// shared copies may contain junk. Luckily we have our local copies to work with :-)[/color]
  }


  [color=#7E7E7E]// do any processing from here onwards[/color]
  [color=#7E7E7E]// only use the local values unAuxIn, unThrottleIn and unSteeringIn, the shared[/color]
  [color=#7E7E7E]// variables unAuxInShared, unThrottleInShared, unSteeringInShared are always owned by[/color]
  [color=#7E7E7E]// the interrupt routines and should not be used in loop[/color]
  
  [color=#CC6600]if[/color](gMode == MODE_RUN)
  {
    [color=#7E7E7E]// we are checking to see if the channel value has changed, this is indicated [/color]
    [color=#7E7E7E]// by the flags. For the simple pass through we don't really need this check,[/color]
    [color=#7E7E7E]// but for a more complex project where a new signal requires significant processing[/color]
    [color=#7E7E7E]// this allows us to only calculate new values when we have new inputs, rather than[/color]
    [color=#7E7E7E]// on every cycle.[/color]
    [color=#CC6600]if[/color](bUpdateFlags & THROTTLE_FLAG)
    {
      [color=#7E7E7E]// A good idea would be to check the before and after value, [/color]
      [color=#7E7E7E]// if they are not equal we are receiving out of range signals[/color]
      [color=#7E7E7E]// this could be an error, interference or a transmitter setting change[/color]
      [color=#7E7E7E]// in any case its a good idea to at least flag it to the user somehow[/color]
[color=#7E7E7E]//      unThrottleIn = constrain(unThrottleIn,unThrottleMin,unThrottleMax);[/color]
      
[color=#7E7E7E]//      if(unThrottleIn > (unThrottleCenter + ERROR_center))[/color]
      {
     [color=#7E7E7E]//   gThrottle = map(unThrottleIn,(unThrottleCenter + ERROR_center),unThrottleMax,PWM_MIN,PWM_MAX);[/color]
        gThrottleDirection = DIRECTION_FORWARD;
      }
[color=#7E7E7E]//      else if (unThrottleIn < (unThrottleCenter - ERROR_center))[/color]
      {
   [color=#7E7E7E]//     gThrottle = map(unThrottleIn,unThrottleMin,(unThrottleCenter- ERROR_center),PWM_MAX,PWM_MIN);[/color]
        gThrottleDirection = DIRECTION_REVERSE;
      }
 
     [color=#7E7E7E]// else[/color]
      {
      gThrottleDirection =DIRECTION_STOP;
      gThrottle=0;
      }
  
      [color=#CC6600]if[/color](gThrottle < IDLE_MAX)
      {
        gGear = GEAR_IDLE;
      }
      [color=#CC6600]else[/color]
      {
        gGear = GEAR_FULL;
      }
    }
  
  [color=#7E7E7E]//  if(bUpdateFlags & STEERING_FLAG)[/color]
    {
      uint8_t throttleLeft = gThrottle;
      uint8_t throttleRight = gThrottle;
  
      gDirection = gThrottleDirection;
      
      [color=#7E7E7E]// see previous comments regarding trapping out of range errors[/color]
      [color=#7E7E7E]// this is left for the user to decide how to handle and flag[/color]
      unSteeringIn = [color=#CC6600]constrain[/color](unSteeringIn,unSteeringMin,unSteeringMax);
  
      [color=#7E7E7E]// if idle spin on spot[/color]
      [color=#CC6600]switch[/color](gGear)
      {
      [color=#CC6600]case[/color] GEAR_IDLE:
        [color=#CC6600]if[/color](unSteeringIn > (unSteeringCenter + RC_DEADBAND))
        {
          gDirection = DIRECTION_ROTATE_RIGHT;
          [color=#7E7E7E]// use steering to set throttle[/color]
          throttleRight = throttleLeft = [color=#CC6600]map[/color](unSteeringIn,unSteeringCenter,unSteeringMax,PWM_MIN,PWM_MAX);
        }
        [color=#CC6600]else[/color] [color=#CC6600]if[/color](unSteeringIn < (unSteeringCenter - RC_DEADBAND))
        {
          gDirection = DIRECTION_ROTATE_LEFT;
          [color=#7E7E7E]// use steering to set throttle[/color]
          throttleRight = throttleLeft = [color=#CC6600]map[/color](unSteeringIn,unSteeringMin,unSteeringCenter,PWM_MAX,PWM_MIN);
        }
        [color=#CC6600]break[/color];
      [color=#7E7E7E]// if not idle proportionally restrain inside track to turn vehicle around it[/color]
      [color=#CC6600]case[/color] GEAR_FULL:
        [color=#CC6600]if[/color](unSteeringIn > (unSteeringCenter + RC_DEADBAND))
        {
          throttleLeft = [color=#CC6600]map[/color](unSteeringIn,unSteeringCenter,unSteeringMax,gThrottle,PWM_MIN);
        }
        [color=#CC6600]else[/color] [color=#CC6600]if[/color](unSteeringIn < (unSteeringCenter - RC_DEADBAND))
        {
          throttleRight = [color=#CC6600]map[/color](unSteeringIn,unSteeringMin,unSteeringCenter,PWM_MIN,gThrottle);
        }
       
        [color=#CC6600]break[/color];
      }
      [color=#CC6600]analogWrite[/color](PWM_SPEED_LEFT,throttleLeft);
      [color=#CC6600]analogWrite[/color](PWM_SPEED_RIGHT,throttleRight);
    }
  }
  
  [color=#CC6600]if[/color]((gDirection != gOldDirection) || (gGear != gOldGear))
  {
    gOldDirection = gDirection;
    gOldGear = gGear;

    [color=#CC6600]digitalWrite[/color](LEFT1,[color=#006699]LOW[/color]);
    [color=#CC6600]digitalWrite[/color](LEFT2,[color=#006699]LOW[/color]);
    [color=#CC6600]digitalWrite[/color](RIGHT1,[color=#006699]LOW[/color]);
    [color=#CC6600]digitalWrite[/color](RIGHT2,[color=#006699]LOW[/color]);

    [color=#CC6600]switch[/color](gDirection)
    {
    [color=#CC6600]case[/color] DIRECTION_FORWARD:
      [color=#CC6600]digitalWrite[/color](LEFT1,[color=#006699]LOW[/color]);
      [color=#CC6600]digitalWrite[/color](LEFT2,[color=#006699]HIGH[/color]);
      [color=#CC6600]digitalWrite[/color](RIGHT1,[color=#006699]LOW[/color]);
      [color=#CC6600]digitalWrite[/color](RIGHT2,[color=#006699]HIGH[/color]);
      [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] DIRECTION_REVERSE:
      [color=#CC6600]digitalWrite[/color](LEFT1,[color=#006699]HIGH[/color]);
      [color=#CC6600]digitalWrite[/color](LEFT2,[color=#006699]LOW[/color]);
      [color=#CC6600]digitalWrite[/color](RIGHT1,[color=#006699]HIGH[/color]);
      [color=#CC6600]digitalWrite[/color](RIGHT2,[color=#006699]LOW[/color]);
      [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] DIRECTION_ROTATE_RIGHT:
      [color=#CC6600]digitalWrite[/color](LEFT1,[color=#006699]HIGH[/color]);
      [color=#CC6600]digitalWrite[/color](LEFT2,[color=#006699]LOW[/color]);
      [color=#CC6600]digitalWrite[/color](RIGHT1,[color=#006699]LOW[/color]);
      [color=#CC6600]digitalWrite[/color](RIGHT2,[color=#006699]HIGH[/color]);
      [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] DIRECTION_ROTATE_LEFT:
      [color=#CC6600]digitalWrite[/color](LEFT1,[color=#006699]LOW[/color]);
      [color=#CC6600]digitalWrite[/color](LEFT2,[color=#006699]HIGH[/color]);
      [color=#CC6600]digitalWrite[/color](RIGHT1,[color=#006699]HIGH[/color]);
      [color=#CC6600]digitalWrite[/color](RIGHT2,[color=#006699]LOW[/color]);
      [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] DIRECTION_STOP:
      [color=#CC6600]digitalWrite[/color](LEFT1,[color=#006699]LOW[/color]);
      [color=#CC6600]digitalWrite[/color](LEFT2,[color=#006699]LOW[/color]);
      [color=#CC6600]digitalWrite[/color](RIGHT1,[color=#006699]LOW[/color]);
      [color=#CC6600]digitalWrite[/color](RIGHT2,[color=#006699]LOW[/color]);
      [color=#CC6600]break[/color];
    }
  }

  bUpdateFlags = 0;
}


[color=#7E7E7E]// simple interrupt service routine[/color]
[color=#CC6600]void[/color] calcThrottle()
{
  [color=#7E7E7E]// if the pin is high, its a rising edge of the signal pulse, so lets record its value[/color]
  [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](THROTTLE_IN_PIN) == [color=#006699]HIGH[/color])
  {
    ulThrottleStart = [color=#CC6600]micros[/color]();
  }
  [color=#CC6600]else[/color]
  {
    [color=#7E7E7E]// else it must be a falling edge, so lets get the time and subtract the time of the rising edge[/color]
    [color=#7E7E7E]// this gives use the time between the rising and falling edges i.e. the pulse duration.[/color]
    unThrottleInShared = (uint16_t)([color=#CC6600]micros[/color]() - ulThrottleStart);
    [color=#7E7E7E]// use set the throttle flag to indicate that a new throttle signal has been received[/color]
    bUpdateFlagsShared |= THROTTLE_FLAG;
  }
}

[color=#CC6600]void[/color] calcSteering()
{
  [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](STEERING_IN_PIN) == [color=#006699]HIGH[/color])
  {
    ulSteeringStart = [color=#CC6600]micros[/color]();
  }
  [color=#CC6600]else[/color]
  {
    unSteeringInShared = (uint16_t)([color=#CC6600]micros[/color]() - ulSteeringStart);
  [color=#7E7E7E]//  bUpdateFlagsShared |= STEERING_FLAG;[/color]
  }
}

[/quote]
 
Odpowiedź
#17
Obojętne o który kod chodzi.
Ten drugi zresztą skopiowałeś z jakimiś znacznikami HTML ze strony internetowej, albo dodałeś je w komentarzu i w ogóle jest nieczytelne co ten program robi.
Nie ma innej filozofii. W C czy Bascom odpala się timer sprzętowy, w nim co np. 10us zmieniasz zmienną, jak dojdzie do 100, to upłynęła 1ms, zliczasz milisekundy (zwiększasz inną zmienną od ms), jak dojdzie do 1000 do minęła 1s, zliczasz sekundy, itd. No oczywiście trzeba było jeszcze sobie na paluszkach policzyć jaki mamy zegar uC, jaki timer używamy, jakie ma tryby działania, jakie mnożniki/dzielniki.
W Arduino już masz to zrobione, nie interesuje Cię jaki to uC i jaki ma zegar, bo dla danej płytki jest to zdefiniowane odgórnie, innych nie ma, wystarczy sprawdzać w loop:
teraz=millis();
jeśli teraz-poprzednio>=1000; to minęła sekunda
poprzednio = teraz; - resetujesz zliczanie
jeśli loop trwa 10us, to sto razy zmienna teraz się nie zmieni, przez 100x999 warunek teraz - poprzednio będzie mniejszy niż 1000, nie upłynęła sekunda, ale przy kolejnym obiegu loop cyknie ten licznik ms do 1000, minie sekunda, zadzieje się coś w programie co wymaga powtarzania co 1s.
Tyle się dzieje w każdej sekundzie działania programu, powinno się dziać. A właściwie to znacznie więcej. A Ty wstawiasz sobie delay 500 i blokujesz normalne działanie.
Oczywiście oprócz samego sprawdzania ile czasu upłynęło wykonujesz różne czynności. Tak jak sobie poustawiasz te warunki możesz zaplanować robić coś co 500ms jak u siebie w programie, a w inne części loop co 20ms, w innej co 150ms, i nieważne (z grubsza) ile takich bloków będziesz miał w programie to one się będą wykonywały w swoim tempie.
Jak wstawisz delay 500 to już nic nie zrobisz w tempie co 50ms.
Poza tym czas się ciągle rozjeżdża, jak masz 1 polecenie to wykonasz co 500ms, jak dodasz kolejne polecenie trwające 20ms to już czas powtarzania zwiększy się do 520ms, to co, skorygujesz delay na 480, potem na 450, znowu coś usuniesz z programu albo wyłączysz komentem by zweryfikować czy to nie powoduje jakiś problemów i znowu musisz wymyślać o ile skorygować delay, by czynności w loop powtarzały się co 500ms.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#18
Jasne delay było żeby spokojnie obserwować taki test nie zatrzymam programu na tak długo , listing poprawiłem i jak mowie, poruszam się jak ślepy bo to zupełnie inny sposób patrzenia na program. Nie rozróżniam polecen, zmiennych itp a masz racje kalibracja jest zbędna bo mozna załozyc ze pod koniec drogi drążka będzie max/min
 
Odpowiedź
#19
Przedstawiłem dwa listingi odczytu wartości sygnału jeden podaje -100,0,100 drugi od 1000 do 2000 ale teraz jak przejść z tych zmiennych na sterowanie ? warunkami pewnie kiedy co i przeliczeniem za inne zmienne ? Cos mi się jakby wyjaśnia ale nie wiem jakie funkcje wybrać będę wdzięczny za podpowiedzi a już resztę doczytam bo owszem czytam poradniki ale cóż jak to na początku za dużo na raz.
 
Odpowiedź
#20
Nie wiem jak to ma działać. W prostych modelach Arduino jak się pchnie joya to przodu to silnik się włącza do przodu, jak do tyłu, to do tyłu.
Jak masz odczyty o zakresie od 1000 do 1500, potem od 1501 do 2000 to można zrobić przestawienie kierunku i podanie sygnału PWM na silnik DC. czyli wartości o rozpiętości 500 przeliczasz na np. PWM o rozpiętości 255, są do tego gotowe funkcje w przykładach Arduino związanych z ANALOG, dział 03, np:

// apply the calibration to the sensor reading
sensorValue = map(sensorValue, sensorMin, sensorMax, 0, 255);
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości