Digital read missing fast switching sensor

I have 16 IR sensors (HW-201), and they are being used to detect slot cars as they pass. At slower speeds the cars are detected just fine, once the cars are going quickly they are detected 9/10 by my arduino mega. The LED to indicate object detection lights up every time the car passes, but the digitalread does not. I am assuming this is beacuse the sensor is high for such a short period of time.

I have had a few ideas to resolve this issue?

  • Tried using fast implementations of digitalRead - unfortunately not quick enough, and I don't think relying on reading in a loop will work
  • Setting them as interrupts, I have an arduino mega and that only supports 6 interrupts, and I have 16 inputs! I could maybe stretch to 2 megas and 8 on each, but three is out of budget and size budget for me.
  • Could I use some sort of flip flop system, or extend the signal in some way? Flip flops seem like they will take up even more pins and will need 32 pins just for the IR sensors! One for state and one for reset, which is possible but seems like I may be over complicating!

Could the cable length be affecting this at all? The cables from IR sensor to arduino is around 50cm.

Hello opugh

Post your current program to see how we can help.

your code might not ping the sensor fast enough but we can't say how to fix this code without seeing it

(you could use pin change interrupt -PCINT0 and PCINT2 would give you 16 pins, enough for you 16 sensors)

Sure! I didn't think the code would be of much use so I didn't include it!

Reading the sensor

#include <Arduino.h>
#include <digitalWriteFast.h>

#include "track_monitor.h"

Checkpoint::Checkpoint(int pin, int position)
    : pin(pin), position(position)
{
    pinMode(pin, INPUT);
}

int Checkpoint::getPosition()
{
    return position;
}

int Checkpoint::getState()
{
    return digitalReadFast(pin);
}

TrackMonitor::TrackMonitor(int *irPins, int numPins) : checkpointCount(numPins), checkpoints(new Checkpoint *[numPins]), lastCheckpoint(checkpoints[0])
{
    // Iterate through the irPins array and create a Checkpoint object for each pin
    for (int i = 0; i < numPins; i++)
    {
        checkpoints[i] = new Checkpoint(irPins[i], i);
    }
}

int TrackMonitor::getPosition()
{
    return lastCheckpoint->getPosition();
}

int TrackMonitor::getCheckpointCount()
{
    return checkpointCount;
}

TrackMonitor::~TrackMonitor()
{
    for (int i = 0; i < checkpointCount; i++)
    {
        delete checkpoints[i];
    }
    delete[] checkpoints;
}

void TrackMonitor::loop()
{
    for (size_t i = 0; i < checkpointCount; i++)
    {

        if (checkpoints[i]->getState() == LOW) // means activated
        {
            Serial.print("detected open: ");
            Serial.println(i + 1);
            lastCheckpoint = checkpoints[i];
        }
    }
}

main

#include <Arduino.h>
#include "car.h"
#include "track_monitor.h"

#define NUM_LANES 2
struct Lane
{
  Car car;
  TrackMonitor trackMonitor;
};

int irPins1[] = {23, 25, 27, 29, 31, 33, 35, 37};
int irPins2[] = {};

float lane1Speeds[sizeof(irPins1) / sizeof(irPins1[0])] = {
    0.1,
    0.5,
    0.1,
    0.1,
    0.1,
    0.1,
    0.1,
    0.1};

Lane lanes[] = {{{M1_FORWARD, M1_BACK, M1_SPEED}, {irPins1, sizeof(irPins1) / sizeof(irPins1[0])}}, {{M2_FORWARD, M2_BACK, M2_SPEED}, {irPins2, sizeof(irPins2) / sizeof(irPins2[0])}}};

void setup()
{
}

void loop()
{
  // run the loop for the sensors

  lanes[0].trackMonitor.loop();
  lanes[1].trackMonitor.loop();
  int currPos = lanes[0].trackMonitor.getPosition();
  lanes[0].car.setSpeed(lane1Speeds[currPos]);
}

here is an example using PCINT where I only read the status of the port getting the action

the buttons in the simulation do not have bouncing to make it easy to see the result

see if that would react fast enough for you (of course printing is slow - you might want to increase baud rate)


source code for reference

// PCINT0  on pins 53 52 51 50 10 11 12 13 ( PORT B)
// PCINT2  A8 ... A15 (PORT K)

const uint8_t portBPins[] = {53, 52, 51, 50, 10, 11, 12, 13};
const uint8_t portKPins[] = {A15, A14, A13, A12, A11, A10, A9, A8};

enum ActionType : uint8_t {NONE, ACTION_PORTB, ACTION_PORTK};
volatile ActionType action = NONE;
volatile uint8_t portState;

ActionType actionCopy;
uint8_t portStateCopy;

void activatePCINT(uint8_t aPin)
{
  *digitalPinToPCMSK(aPin) |= bit (digitalPinToPCMSKbit(aPin));  // enable it
  PCIFR  |= bit (digitalPinToPCICRbit(aPin)); // clear interrupt flag
  PCICR  |= bit (digitalPinToPCICRbit(aPin)); // enable interrupt
}

ISR (PCINT0_vect) {
  action = ACTION_PORTB;
  portState = PINB;
}

ISR (PCINT2_vect) {
  action = ACTION_PORTK;
  portState = PINK;
}

void printAction() {
  for (int8_t i = 7; i >= 0; i--) Serial.write(bitRead(portStateCopy, i) == 0 ? '-' : '*');
  Serial.println(actionCopy == ACTION_PORTB ? F("\tPB ") : F("\tPK "));
}

void setup() {

  for (uint8_t aPin : portBPins) {
    pinMode( aPin, INPUT_PULLUP);
    activatePCINT(aPin);
  }

  for (uint8_t aPin : portKPins) {
    pinMode( aPin, INPUT_PULLUP);
    activatePCINT(aPin);
  }

  Serial.begin(115200);
  Serial.println(F("Ready"));
}

void loop() {
  switch (action) {
    case NONE:
      break;

    case ACTION_PORTB:
    case ACTION_PORTK:
      // critical section
      noInterrupts();
      actionCopy = action;
      portStateCopy = portState;
      action = NONE;
      interrupts();
      printAction();
      break;
  }
}

This is really interesting! And looks like it could well be the solution. I am looking at using 16 pins so will need to work out how to add a few more. I will give this a go and will report how I get on. Thank you!

Using Serial print of each active position make you code very slow.

BTW, it seems you use Serial without initialise it.

I did not bother to add 16 buttons but you have 16 active pins

That’s the ones to use

You are dead right! I cleaned up the code to remove anything not useful for this post, I was just using serial to debug another issue and left them in! Good spot though!

Ah I didn't spot that part! Thank you for your help!

That worked perfectly! Thank you!

Good news

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.