logic for edge avoider program - c

The microcontroller is AVR and the processor in it is ATMEGA8. I wrote a piece that followed the black color. It is like :
#include<avr/io.h>
#include<util/delay.h>
int main()
{
int rs,ls; // denotes the right sensor and left sensor respectively
DDRC=0x00; // DENOTES THAT WE TAKE INPUT FROM THE SENSER
DDRB=0xFF; // DENOTES THAT PORT IS MEANT FOR THE OUTPUT FROM THE MOTOR
while(1) {
ls=PINC&0b0000001; // last bit on
rs=PINC&0b0001000; // 1st bit on
if((ls==0b0000001)&(rs==0b0001000))
PORTB=0b00010010; // forward
if((ls==0b0000001)&(rs==0b0000000))
PORTB=0b00000010; // right
if( (ls==0b0000000) & (rs==0b0001000))
PORTB=0b00010000; // left
if((ls==0b0000000)&(rs==0b0000000) )
PORTB=0b00010010; // stop
}
}
I am trying to write for the edge avoider. It has the same sensors that detect the black color. But now those sensers have to avoid a pit while moving on the table. I am unable to decide as to how i can do this.
NOTE : Sensor is able to detect the pit if there is nothing beneath it. But how do I am having problem writing code.

There can be many solutions for Edge Avoider. One implementation I have seen is -
Explanation -
If none (left & right) is black (black = edge, white = table surface), you can keep moving forward.
If any/both are black, you need to back off a little (CAUTION : This is tricky, in backing also, you may end up falling), and then change direction.
You need to experiment with delays, to get appropriate working.
These are the values needed below (I had omitted them before, because they are dependent on configuration)-
int move_backward = 0b00000110;
int right_turn = 0b00001010;
int move_forward = 0b00001001;
int left_turn = 0b00000101;
int left_sensor_on = 0b0010000;
int right_sensor_on = 0b0100000;
int left_sensor_off = 0b0000000;
int right_sensor_off = 0b0000000;
The below code should go inside while (1)
left_sensor = (PINC & 0b0000001); // This depends upon your configuration
right_sensor = (PINC & 0b0001000); // So I have used, the one from your code
if ((left_sensor==left_sensor_off) & (right_sensor==right_sensor_off))
{
PORTB = move_backward; //move backward
_delay_ms(50);
PORTB=right_turn; //take a right turn
_delay_ms(30);
left_sensor = 0;
right_sensor = 0;
}
if ((left_sensor==left_sensor_on) & (right_sensor==right_sensor_on))
{
PORTB = move_forward; //move forward
left_sensor = 0;
right_sensor = 0;
}
if ((left_sensor==left_sensor_off) & (right_sensor==right_sensor_on))
{
PORTB = move_backward;
_delay_ms(50);
PORTB = right_turn;
_delay_ms(30);
left_sensor = 0;
right_sensor = 0;
}
if ((left_sensor==left_sensor_on) & (right_sensor==right_sensor_off))
{
PORTB = move_backward;
_delay_ms(50);
PORTB = left_turn;
_delay_ms(30);
left_sensor = 0;
right_sensor = 0;
}

Related

Call of function without prototype error message with Delay1TCYx (1) ( C language )

We have a project that were running using C and a PICkit 3. Our issu is that we remain getting the same error message and arent sure whta the issue is. Any help / advice would be great.
void main (void)
{
ANSEL = 0; //turn off all other analog inputs
ANSELH = 0;
ANSELbits.ANS0 = 1; // turn on RA0 analog
ADCON0 = 1; // justify right
ADC_Init(); // Call ADC_Init function
ADC_Convert();
Delay1TCYx(1); //delay 1 x 1 cycles
int reading0 = ADRESL + (ADRESH * 256); //convert result to 10 bits
if (reading0 = 0b1000000011)
{
readingsamples();
}
while(1);
}

Losing data bit when reading from GPIO by libgpiod on Linux

I am using Debian (8.3.0-6) on an embedded custom board and working on the dht11 sensor.
Briefly,
I need to read 40 bits from a GPIO pin and each bit can take a max 70 microseconds. When bit-level is high for max 28us or 70us, it means is logic 0 or 1, respectively. (So I have a timeout controller for each bit and if a bit takes more than 80us, I need to stop the process.).
In my situation, sometimes I can read all 40 bits correctly but sometimes I can't do it and the function of libgpiod gpiod_line_get_value(line); is missing the bit (my code is below). I am trying to figure out that why I cant read and lose a bit, what is the reason for that. But I haven't found a sensible answer yet. So I was wondering What am I missing out?, What is the proper way to GPIO programming?
Here is what I wanted to show you, How do I understand what I am missing a bit? Whenever I catch a bit, I am setting and resetting another GPIO pin at the rising and falling edge of a bit (So I can see which bit missing). Moreover, as far as I see I am always missing the two edges on one bit or one edge on two bits consecutively (rising and falling or falling and rising). In the first picture, you can see which bit I missed, the second is when I read all bits correctly.
Here it is my code:
//********************************************************* Start reading data bit by low level (50us) ***************************
for (int i = 0; i < DHT_DATA_BYTE_COUNT ; i++) //DHT_DATA_BYTE_COUNT = 5
{
for (int J = 7; J > -1; J--)
{
GPIO_SetOutPutPin(testPin); //gpiod_line_set_value(testPin, 1);
int ret;
start = micros();
do
{
ret = GPIO_IsInputPinSet(dht11pin);//gpiod_line_get_value(dht11pin);
delta = micros() - start;
if(ret == -1)
{
err_step.step = 9;
err_step.ret_val = -1;
return -1;
}
if(delta > DHT_START_BIT_TIMEOUT_US) //80us
{
err_step.step = 10;
err_step.ret_val = -2;
err_step.timestamp[is] = delta;
err_step.indx[is].i = i;
err_step.indx[is++].j = J;
GPIO_ResetOutPutPin(testPin);
return -2;
}
}while(ret == 0);
GPIO_ResetOutPutPin(testPin);
err_step.ret_val = 10;
GPIO_SetOutPutPin(testPin);
start = micros();
do
{
ret = GPIO_IsInputPinSet(dht11pin);
delta = micros() - start;
if(ret == -1)
{
err_step.step = 11;
err_step.ret_val = -1;
return -1;
}
if(delta > DHT_BEGIN_RESPONSE_TIMEOUT_US) //80us
{
err_step.step = 12;
err_step.ret_val = -2;
err_step.timestamp[is] = delta;
err_step.indx[is].i = i;
err_step.indx[is++].j = J;
return -2;
}
}while(ret == 1);
err_step.timestamp[is] = delta;
err_step.indx[is].i = i;
err_step.indx[is++].j = J;
GPIO_ResetOutPutPin(testPin);
err_step.ret_val = 10;
(delta > DHT_BIT_SET_DATA_DETECT_TIME_US) ? bitWrite(dht11_byte[i],J,1) : bitWrite(dht11_byte[i],J,0);
}
}

How to detect the release of a switch in a keyboard matrix using a microcontroller?

I want to detect the release of a switch in a matrix of keys. Consider a 4*4 keys matrix, a scan by a microcontroller can easily be done to detect a key PRESS. However, I want to detect also the releases when they occur.
Is there a more efficient way to do so than just doing another scan on each state change interrupt for the unpressed ones?
Matrix keyboard scanning does not require any interrupt. You should create scanning function that will be called periodically. The best way is to store each key as a bit in some variable - you have 4x4 keyboard so uint16_t will perfetly fit. XOR operator is perfect for key change detection. Also don't forget to implement some key debouncing functionality.
I'd suggest following "pseudo" code or something similar (I hope there is no bug in it):
#define ROW_COUNT 4
#define COL_COUNT 4
#define DEBOUNCE_TIMEOUT 10 // In milliseconds
typedef uint16_t KeyState;
// This function returns current keyboard state and
// fills upKeys with keys that were pressed and downKeys with keys that were released
// It expects that key down is logic H, up is logic L
KeyState KeyboardState(KeyState* upKeys, KeyState* downKeys)
{
static KeyState lastState = 0;
static KeyState lastValidState = 0;
static Timestamp lastTimestamp = 0;
KeyState currentState = 0;
uint8_t x, y;
// Set defaults
if (upKeys)
*upKeys = 0;
if (downKeys)
*downKeys = 0;
for(y = 0; y < ROW_COUNT; y++)
{
// Set appropriate row pin to H
SetRowPinH(y);
// Just to be sure that any parasitic capacitance gets charged
SleepMicro(10);
for(x = 0; x < COL_COUNT; x++)
{
// Check key pressed
if (IsColPinSet(x))
currentState |= 1 << ((y * COL_COUNT) + x);
}
// And don't forget to set row pin back to L
SetRowPinL(y);
}
// Now lets do debouncing - this is important for good functionality
// Matrix state should not change for some time to accept result
if (lastState == currentState)
{
// Check if time has passed
if ((TimestampNowMilli() - lastTimestampMilli) >= DEBOUNCE_TIMEOUT)
{
// Let's detect up/down changes first - it's easy, just use XOR for change detection
if (upKeys)
*upKeys = currentState & (lastValidState ^ currentState);
if (downKeys)
*downKeys = (~currentState) & (lastValidState ^ currentState);
lastValidState = currentState;
}
}
else
{
// Current state differs from previous - reset timer
lastTimestampMilli = TimestampNowMilli();
}
lastState = currentState;
return lastValidState;
}
int main()
{
KeyState upKeys;
KeyState downKeys;
KeyState currentKeys;
while(1)
{
currentKeys = KeyboardState(&upKeys, &downKeys);
if (upKeys & 0x0001)
printf("Key 1 pressed\n");
if (downKeys & 0x0001)
printf("Key 1 released\n");
}
}

Arduino IR sensor - low range

I'm programming Arduino. I have a problem with the IR sensor. It only detects this ball (equiped with IR LEDS) in range of 0,5m and I would need at least 2m. This is the ball:
"http://drgraeme.net/drgraeme-free-nxt-g-tutorials/Ch108/SoccerGenIINXTG/Soccer%20Ball/HiTechnicRCJ05V2.jpg"
and this is my arduino code:
// digital pin 2 has a pushbutton attached to it. Give it a name:
int IR = 2;
int i = 0;
int ii = 0;
int led = 0;
void setup()
{
Serial.begin(9600);
pinMode(IR, INPUT_PULLUP);
pinMode(led, OUTPUT);
}
void loop() {
i = 0;
ii = 0;
do
{
i = i + 1;
int STANJE1 = digitalRead(IR);
if(STANJE1 < 1)
{
ii = ii + 1;
}
}while(i<1000);
if(ii > 1)
{Serial.println("IS");}
else{Serial.println("IS NOT");}
}
IR sensor is 38kHZ and the balls LEDs are 40kHZ, but I found a program that allowed me to detect the ball 10m away from sensor, but It was ment for something else, and I didn't understand it, so that is not the problem.
This is the code that works further (That's because it doesn't use "DigitalRead()")
/* Raw IR decoder sketch!
This sketch/program uses the Arduno and a PNA4602 to
decode IR received. This can be used to make a IR receiver
(by looking for a particular code)
or transmitter (by pulsing an IR LED at ~38KHz for the
durations detected
Code is public domain, check out www.ladyada.net and adafruit.com
for more tutorials!
*/
// We need to use the 'raw' pin reading methods
// because timing is very important here and the digitalRead()
// procedure is slower!
//uint8_t IRpin = 2;
// Digital pin #2 is the same as Pin D2 see
// http://arduino.cc/en/Hacking/PinMapping168 for the 'raw' pin mapping
#define IRpin_PIN PIND
#define IRpin 2
// the maximum pulse we'll listen for - 65 milliseconds is a long time
#define MAXPULSE 65000
// what our timing resolution should be, larger is better
// as its more 'precise' - but too large and you wont get
// accurate timing
#define RESOLUTION 20
// we will store up to 100 pulse pairs (this is -a lot-)
uint16_t pulses[100][2]; // pair is high and low pulse
uint8_t currentpulse = 0; // index for pulses we're storing
void setup(void) {
Serial.begin(9600);
Serial.println("Ready to decode IR!");
}
void loop(void) {
uint16_t highpulse, lowpulse; // temporary storage timing
highpulse = lowpulse = 0; // start out with no pulse length
// while (digitalRead(IRpin)) { // this is too slow!
while (IRpin_PIN & (1 << IRpin)) {
// pin is still HIGH
// count off another few microseconds
highpulse++;
delayMicroseconds(RESOLUTION);
// If the pulse is too long, we 'timed out' - either nothing
// was received or the code is finished, so print what
// we've grabbed so far, and then reset
if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
printpulses();
currentpulse=0;
return;
}
}
// we didn't time out so lets stash the reading
pulses[currentpulse][0] = highpulse;
// same as above
while (! (IRpin_PIN & _BV(IRpin))) {
// pin is still LOW
lowpulse++;
delayMicroseconds(RESOLUTION);
if ((lowpulse >= MAXPULSE) && (currentpulse != 0)) {
printpulses();
currentpulse=0;
return;
}
}
pulses[currentpulse][1] = lowpulse;
// we read one high-low pulse successfully, continue!
currentpulse++;
}
void printpulses(void) {
Serial.println("\n\r\n\rReceived: \n\rOFF \tON");
for (uint8_t i = 0; i < currentpulse; i++) {
Serial.print(pulses[i][0] * RESOLUTION, DEC);
Serial.print(" usec, ");
Serial.print(pulses[i][1] * RESOLUTION, DEC);
Serial.println(" usec");
}
}

How Can I change objects name by a loop in C lang?

How Can I change objects name by a loop?
I want create a light effect like knight-rider's one. With a PIC
I thought instead of turning on and off manually to use a loop for change RB line number.
I want to change the last number of this Port line name: like RB01 RB02 like this
my code is like this
for(int i = 0; i>6 ; i++ ){
PORTB = 0X00;
RB+i = 1;
}
Are there any kind of method do something like this? thanks
Assuming RB01, RB02, etc are just convenient #defines for accessing the bits in PORTB, you can write the loop with bitwise arithmetic and not use RB0* at all.
for ( int i = 0; i != 6; ++ i ) {
PORTB = 1 << i; /* one light at a time */
/* or */
PORTB = ( 1 << i + 1 ) - 1; /* light all in sequence */
}
It's not very elegant, but one way is to do it like this:
PORTB = 0x00;
for (i = 0; i < 6; ++i)
{
RB00 = (i == 0);
RB01 = (i == 1);
RB02 = (i == 2);
RB03 = (i == 3);
RB04 = (i == 4);
RB05 = (i == 5);
// note: you probably want to put a delay in here, e.g. 200 ms
}
If you want to keep the previous LEDs on each time you turn on a new one then you can do that like this:
PORTB = 0x00;
for (i = 0; i < 6; ++i)
{
RB00 = (i >= 0);
RB01 = (i >= 1);
RB02 = (i >= 2);
RB03 = (i >= 3);
RB04 = (i >= 4);
RB05 = (i >= 5);
// note: you probably want to put a delay in here, e.g. 200 ms
}
No, there is no way to "generate" symbol names that way. You can use bit masks for manipulating the latch register of the port in question.
I would probably use a table:
struct portbits
{
sometype bit; // Not quite sure what "RB0..RB5" actually translate to.
};
struct portbits bits[] =
{
RB00,
RB01,
RB02,
RB03,
RB04,
RB05,
RB06,
RB07,
};
for(i = 0; i < 7; i++)
{
bits[i] = 1;
}

Resources