I'm making this project that includes sensors. I have two sensors, one at left and right. I have succeeded detecting left and right motions, but when I just spam "sense" a sensor, let's say left sensor, it reads as i have swiped left. Can you tell me what's the problem?
to understand my code I have drawn the "required" sequence to say that I have swiped. (0 detected, 1 nothing detected)
For left
1. L=1, R=1
2. L=0, R=1
3. L=0, R=0
4. L=1, R=0
For right
1. L=1, R=1
2. L=1, R=0
3. L=0, R=0
4. L=0, R=1
Here's my code
int rs=7,ls=6,r,l,x,xx,xxx,z; //rs right sensor, ls left sensor
void setup() {
Serial.begin(9600);
pinMode(rs, INPUT);
pinMode(ls, INPUT);
pinMode(13,OUTPUT);
}
void loop() {
digitalWrite(12,LOW);
digitalWrite(13,LOW);
r= digitalRead(rs);
l= digitalRead(ls);
if(r==1&&l==1)
x=1;
else x=0;
//RIGHT MOTION
if(x==1){
for(z=1;z<10000;z++){
if(digitalRead(ls)<digitalRead(rs)){
z=10000;xx=1;}}
if(xx=1){
for(z=1;z<10000;z++){
if(digitalRead(ls)==0&&digitalRead(rs)==0){
z=10000;xxx=1;}}}
if(xxx==1){
for(z=1;z<10000;z++){
if(digitalRead(ls)>digitalRead(rs)){
z=10000;Serial.println("Right motion");digitalWrite(12,HIGH);}}}}
//LEFT MOTION
if(x==1){
for(z=1;z<10000;z++){
if(digitalRead(ls)>digitalRead(rs)){
z=10000;xx=1;}}
if(xx=1){
for(z=1;z<10000;z++){
if(digitalRead(ls)==0&&digitalRead(rs)==0){
z=10000;xxx=1;}}}
if(xxx==1){
for(z=1;z<10000;z++){
if(digitalRead(ls)<digitalRead(rs)){
z=10000;Serial.println("Left motion");digitalWrite(13,HIGH);}}}}
}
I set my loop 10000 times because 1 whole loop is so fast to detect a motion.
Thanks in advance.
In short: You never reset your vars x, xx, xxx back to 0. Also you use both "Sets" of variables for both kinds of Motion. So the
digitalRead(ls) < digitalRead(rs)
sets xx = 1 and
digitalRead(ls) > digitalRead(rs)
Also sets xx = 1.
The first thing to do would be to name the "first" (everything after //RIGHT MOTION to //LEFT MOTION) x, xx, xxx to something like: rightMotionStep1 rightMotionStep2 and rightMotionStep3 and the later x, xx, xxx to: leftMotionStep1 leftMotionStep2 and leftMotionStep3.
of course you also have to declare these Vars.
The next thing is that you have to reset all of the vars so after your
Serial.println("Right motion");
there should be
rightMotionStep1 = 0;
rightMotionStep2 = 0;
rightMotionStep3 = 0;
same thing for left motion.
Related
can someone slap me an idea or math formula on how to make my enemies move in a sine wave
tried something like this but they just move at the same time so they just create a straight line of enemies moving left and right.
for(int i = 0; i < 5; i++){
float y = sinf( 100+delta_time*0.06f) * 75;
float x = game->enemy[i].base_x + y;
game->enemy[i].x = x ;
game->enemy[i].y += 1;
SDL_Rect rect = { game->enemy[i].x , game->enemy[i].y ,game->enemy[i].w, game->enemy[i].h};
SDL_RenderCopy(game->renderer , game->enemy[i].sprite , NULL , &rect);
}
Let v=(v_x,v_y) be the overall direction of the enemy. Let o be the vector o=(-v_y/||v||,v_x/||v||) where ||v||=sqrt(v_x.v_x+v_y.v_y) is the norm of v. The vector o is perpendicular to v. A sinusoidal motion is wanted in that direction. Consequently, the position p(t)=(x(t),y(t)) is defined as :
x(t)=v_x.t-A.v_y/||v||.sin(w.t)
y(t)=v_y.t+A.v_x/||v||.sin(w.t)
where A is the magnitude of the ossilations and w the pulsation of the ossilations. The corresponding frequency is f=w/(2pi).Then, the wavelength lambda=||v||/f corresponds to the length of ossilations.
If the enemy is moving in the x direction (v_y=0) then :
x(t)=v_x.t
y(t)=A.sin(w.t)
The length of ossilations is lambda=2pi.v_x/w.
I have some sources with coordinates (xn, yn, zn) w.r.t a center C of a ring and unit vectors (ns_ux, ns_uy, ns_uz) along my line of sight. I want to calculate whether these sources pass through a cylinder of inner and outer radius 9.5 and 10.5 units, respectively. If they intersect this cylinder (or I call it ring, sometimes), then I would like to calculate the length of this intercept. My position is outside of this ring and there are sources which lie beyond the center C on the other side. These sources, therefore will pass through this ring twice. This picture should help visualize this problem.
#define PI 3.142
int main(){
int k,number=200;
float r_min=9.50000;
float r_max=10.500000;
float step=0.3;
float z_c = 3.0;
float ns_ux[number],ns_uy[number],ns_uz[number],xn[number], yn[number],zn[number],l[number],b[number],ns[number],x_comp,y_comp,z_comp,radial;
FILE* val= NULL;
val=fopen("novae_uniform_unitvectors.txt", "r");
for(k=0;k<=(number-1);k++){
fscanf(val,"%f %f %f %f %f %f %f %f %f", &xn[k], &yn[k], &zn[k], &ns_ux[k], &ns_uy[k], &ns_uz[k], &l[k], &b[k], &ns[k]);
float u=0.;
for (u=0.;u<=30.;u=u+step){
x_comp=xn[k]+u*ns_ux[k];
vector addition : calculating the x_comp w.r.t the center C when stepped by 'u' units along my l.o.s.
y_comp=yn[k]+u*ns_uy[k];
radial=pow((x_comp*x_comp+y_comp*y_comp),0.5);
if (radial >=r_min && radial <=r_max){
z_comp=zn[k]+u*ns_uz[k];
checking if the height is consistent with the ring's height
if(z_comp >=-z_c && z_comp <= z_c)
printf("%f\t%f\t%f\t%f\n",l[k],u, z_comp, radial);
}
}
}
return 0.;
}
This 'radial' values gives me a list of points where my line of sight intersects with the ring. But, I require only the end points to calculate the length of the intercept on the ring.
e.g. in the case listed below, my l.o.s. passes through the ring at I and then comes off at II. Then it keeps going until it hits the ring again at III and then come out of it at IV. I need to store only I, II , III and IV points in my file. How would I be able to do it ?
longitude..........u........ z_comp........radial
121.890999 0.100000 0.016025 9.561846 I
121.890999 0.200000 0.038453 9.538050
121.890999 0.300000 0.060881 9.515191 II
121.890999 4.799998 1.070159 9.518372 III
121.890999 4.899998 1.092587 9.541364
121.890999 4.999998 1.115016 9.565292
...... skipping to save space........
121.890999 7.399995 1.653297 10.400277
121.890999 7.499995 1.675725 10.444989
121.890999 7.599995 1.698153 10.490416 IV
Figured out a way to store only the final and initial values by using a boolean operator as follows (continued from the code in the question) :
define bool change = true;
...(rest of the program)...
if(radial >= r_min && radial <= r_max) {
z_comp = zn[k] + u * ns_uz[k];
if (z_comp >= -z_c && z_comp <= z_c)
if (change) {
printf("%f\t%f\t%f\t%f\t", l[k], b[k], ns[k], radial[i]);
change = !change;
}
} else { // if the condition of radial and z_comp is not met
if (!change) {
fprintf(fp, "%f\n", radial[i - 1]);
change = !change;
}
}
This would store only the first and the last values of the radial component (i.e. the end points of the intercept of the line of sight vector on the ring)
I'm a bit of an openGL/programming noobie so I'm trying to make an "AI" for the right paddle. I know this isnt the proper way of doing it, what I SHOULD be doing is making it follow the ball. But right now I'm just trying to make it perpetually move up and down. I can't figure out how to do it, trying to use If loops like
if (paddle.pos[1] > 1){
paddle.pos[1] = paddle.pos[1] - delta}
I set delta to something like 0.01, 1 is the top of the screen. Obviously this isnt right because as soon as it goes down below 1 it goes up again, but I'm trying to do something like it.
2nd question - How do you move the ball from 0,0 when it starts? Kind of the same problem, am using if statements with the x values but thats definitely not right.
This is using C by the way.
Try something like this to make pos repeatedly go from 0 to 1 and back to 0:
// Initialize.
float pos = 0.0f;
float delta = 0.01f;
// On every update.
pos += delta;
if (pos > 1.0f) {
pos = 1.0f;
delta = -delta;
} else if (pos < 0.0f) {
pos = 0.0f;
delta = -delta;
}
The key here is that you invert the sign of your increment each time you reach one of the end positions.
Traversing INT array in two ways is a robotic funny code (in C).
I have an array of positions like this: int pos[] = {0, 45, 90, 135, 180, 135, 90, 45};
These positions are used to move a servo motor.
45 90 135
\ | /
\ | /
\ | /
0 ----------- 180
In main loop() I check distance from an obstacle, and if it's < xx Cm my servo must rotate to next step (next array position) until it finds a free way ( > xx Cm ).
My main is easy:
int main (int argc, const char * argv[]) { for (;;) find(); }
and my core function (find) is this:
void find() {
for ( i=0; i<sizeof(pos); i++ ) // Traversing position array
{
distance = rand() % 7; // Simulate obstacle distance
move( pos[i] ); // Simulate movements
if (i==sizeof(pos)) { i=1; } // Try to reset the "i" counter. PROBLEM!
if ( distance<=5 ) continue; // Is there an obstacle?
sleep(2); // Debug sleep
find(); // Similar recursion
}
}
I don't know what is wrong in this code, but I need to move servo until is there not an obstacle.
Example:
At position 90 I find an obstacle. I want to loop array from left to right and viceversa controlling distance every step. If I don't find a freeway, print("ko") else print("ok").
How do I fix this code to work correctly?
You really want i < sizeof(pos) / sizeof(*pos) rather than i < sizeof(pos). The size of an array is not the number of its elements but rather the total byte count it occupies in memory.
sizeof(pos) yields 8 * sizeof(int). If an int is 4 bytes, you are looping 32 times instead of 8.
Also, i == sizeof(pos) will never be true in the body of the loop because the condition of the for statement limits i to sizeof(pos) - 1.
If I understand your question correctly, you want the servo to make a sweeping movement from left to right and then back from right to left. Measuring the distance to an object that can be in front of the robot at each angle. If there is a free way ahead of the robot, the find method returns.
int pos[] = {0, 45, 90, 135, 180, -1};
void find()
{
int i = 0;
int direction = 1;
do {
move(pos[i]);
i += direction;
if (pos[i+direction] == -1) direction = -1;
if (i==0) direction = 1;
} while(measure_distance() <= 5);
}
Instead of recursion, there is a while loop that only exits when there is a distance greater then 5.
The 'pos' array has a sentinel at the end (-1). This is an invalid angle and can be used to find the end of the array. There is no need to calculate the number of elements.
The left-right, right-left movement comes from using the 'direction' variable. It is rather easy to detect either the beginning (i==0) or the end of the 'pos' array (pos[i+1] == -1), at which point we reverse the direction.
There is also no need to repeat the angles after 180 degrees. The sequence we get is:
0 45 90 135 180 135 90 45 0 45 90 ...
We can even reduce the code with one line...
...
if (pos[i+direction] == -1 || i == 0) direction *= -1;
...
Cheers,
Johan
Don't forget to initialize your rand function using
/* initialize random seed: */
srand ( time(NULL) );
distance = rand() % 7;
It's probably good practise to say:
#define POSLENGTH 8
and then iterate using i<POSLENGTH: as others have pointed out using sizeof(pos) is probably not going to work.
Also, arrays in C are 0 based: elements go 0,1,2,3,...n-1.
So, you need to say:
if (i==POSLENGTH-1) i=0;
Try using a while loop instead of a for loop. Increment the value when there is no obstacle and break when you find an obstruction:
{
......
......
i = rand()%7;
move( pos[i]);
if (i<5)
break;
else
continue;
.......
.......
}
This will randomly choose the position until you get an obstacle and also there will be no need to reset it as the loop will automatically break on encountering an obstacle.
I'm making a driver for an 8x8 LED matrix that I'm driving from a computer's parallel port. It's meant to be a clock, inspired by a design I saw on Tokyoflash.
Part of the driver is an array of 3*5 number "sprites" that are drawn to the matrix. A coordinate of the matrix is assigned to a coordinate of the sprite and so forth, until the entire sprite is drawn on it. This process is repeated for the other digit with an offset. I have verified I have drawn the sprites correctly, and that the matrix is blank when it is written to. However, when I draw a number on the matrix I get errant 1s at Numpad6 for the left digit, Numpad1 for the right (Example with the left digit not drawn.)
I have a week of experience in C and this is baffling me.
Here is the driver in full if you want to compile it yourself. It is nowhere near finished.
//8x8 LED MATRIX DRIVER VER 0.1 APR062009
//CLOCK
//
// 01234567
// 0 BXXXXXXH B: Binary Mode Indicator
// 1 DXXXXXXM D: Decimal Mode Indicator
// 2 NNNNNNNN H: Hour Centric Display
// 3 LLLNNRRR M: Minute Centric Display
// 4 LNLNNRNR X: Secondary Information
// 5 LLLNNRRR L: Left Digit
// 6 LNLNNRNR R: Right digit
// 7 LLLNNRRR N: Not Used
#include <stdio.h>
#include <unistd.h>
//#include <math.h>
#include <time.h>
#include </usr/include/sys/io.h>
#define BASEPORT 0x378
int main()
{
//Increasing array parameters to seems to reduce glitching [best 10 5 3]
int Dig[10][5][3] = {0}; //ALPHANUMERIC ARRAY [NUMBER (0..9)][Y(0..4)][X(0..2)]
int Mat[7][7] = {0}; //[ROW][COL], Top L corner = [0][0]
int Aux1[7] = {0}; //Topmost Row
int Aux2[7] = {0}; //Second to Topmost Row
int Clk; //Clock
int Wait; //Delay; meant to eventually replace clock in its current state
int C1; //Counters
int C2;
int C3;
int L; //Left Digit
int R; //Right Digit
//break string left undefined atm
//ioperm (BASEPORT, 3, 1);
//outb(0, BASEPORT);
printf("Now running.\n");
//Set Variables
//3D DIGIT ARRAY [Num][Row][Col] (INITIALIZED BY INSTRUCTIONS)
//Dig array is meant to be read only once initialized
//3D arrays are unintuitive to declare so the numbers are
//"drawn" instead.
//Horizontals
//Some entries in the loop may have the variable in the middle
//coordinate instead of the 3rd and/or with a +2. This is to
//incorporate the incomplete columns some numbers have (eg "2") and
//saves coding additional loops.
for(C1=0; C1<=2; C1++){
Dig[0][0][C1]=1; Dig[0][4][C1]=1;
Dig[2][0][C1]=1; Dig[2][2][C1]=1; Dig[2][4][C1]=1; Dig[2][C1][2]=1; Dig[2][C1+2][0]=1;
Dig[3][0][C1]=1; Dig[3][2][C1]=1; Dig[3][4][C1]=1;
Dig[4][2][C1]=1; Dig[4][C1][0]=1;
Dig[5][0][C1]=1; Dig[5][2][C1]=1; Dig[5][4][C1]=1; Dig[5][C1][0]=1; Dig[5][C1+2][2]=1;
Dig[6][0][C1]=1; Dig[6][2][C1]=1; Dig[6][4][C1]=1; Dig[6][C1+2][2]=1;
Dig[7][0][C1]=1;
Dig[8][0][C1]=1; Dig[8][2][C1]=1; Dig[8][4][C1]=1;
Dig[9][0][C1]=1; Dig[9][2][C1]=1; Dig[9][4][C1]=1; Dig[9][C1][0]=1;
}
//Verticals
for(C1=0; C1<=4; C1++){
Dig[0][C1][0]=1; Dig[0][C1][2]=1;
Dig[1][C1][2]=1;
Dig[3][C1][2]=1;
Dig[4][C1][2]=1;
Dig[6][C1][0]=1;
Dig[7][C1][2]=1;
Dig[8][C1][0]=1; Dig[8][C1][2]=1;
Dig[9][C1][2]=1;
}
Clk=10000;
L=2; //Think about incorporating overflow protection for L,R
R=4;
//Print Left Digit to Matrix # (3, 0)
for(C1=0; C1<=4; C1++){ //For some reason produces column of 1s at numpad 6
for(C2=0; C2<=2; C2++){
Mat[C1+3][C2]=Dig[L][C1][C2];
printf("%d", Dig[L][C1][C2]); //Debug
}
printf(" %d %d %d\n", L, C1, C2); //Debug
}
//Print Right Digit to Matrix # (3, 5)
for(C1=0; C1<=4; C1++){ //For some reason produces column of 1s at numpad 1
for(C2=0; C2<=2; C2++){
Mat[C1+3][C2+5]=Dig[R][C1][C2];
}
}
//X Test Pattern
//for(C1=0; C1<=7; C1++){
// Mat[C1][C1]=5;
// Mat[7-C1][C1]=5;
//}
usleep(Clk);
//while(1){
//Breakfree [NOT FUNCTIONAL]
//Break_String=getch(); (Getch is not ANSI, need ncurses)
//if(Break_String != -1){
// if(Break_String = 27){
// break;
// }
//}
//Terminal Display
//for(C3=0; C3<=9; C3++){ //Debug Digit array [Successful, numbers draw correctly]
// for(C2=0; C2<=4; C2++){
// for(C1=0; C1<=2; C1++){
// printf("%d", Dig[C3][C2][C1]);
// }
// printf("\n");
// }
//printf("\n");
//usleep(1000000); //Debug
//}
usleep(3000000); //Debug
for(C1=0; C1<=7; C1++){ //Prints to terminal every second, when looping
for(C2=0; C2<=7; C2++){
printf("%d", Mat[C1][C2]);
}
printf("\n");
}
printf("\n");
//Hardware Display
for(C1=0; C1<=29; C1++){ //30 Hz
for(C3=0; C3<=7; C3++){ //COLUMN
//printf("%d %d \n", C3, C1); //Loop Debug
usleep(1000);
//CLOCK GROUND TO GO HERE, OUT STATUS
//for(C2=0; C2<=7; C2++){ //PX
//outb(Mat[C3][C2], BASEPORT);
//}
}
usleep(4*Clk);
}
//}
//ioperm(BASEPORT, 3, 0);
exit(0);
}
Also, I had to make my Sprite array bounds each one bigger than they should have been to make it work. I figure this is all some some memory snafu but I'm nowhere near that proficient in C to know what to do.
I would greatly appreciate any help.
I need to look through it more but one problem off the bat is that you're driving an 8x8 LED matrix but using a 7x7 matrix to hold the data. Declare your matrix as:
int Mat[8][8];
Bryan, I think you are just missing the fundamental understanding of how array indices work in C.
When you declare
int array[N]
you access the elements in a range of
array[0] ... array[N-1]
which gives you a total of N elements.
For example:
int array[4]
gives you
array[0]
array[1]
array[2]
array[3]
for a total of 4 elements.
When looping over this array, this is the convention that's almost always used:
for(i = 0; i < 4; i++)
I think that this issue is causing multiple problems in your code and if you go back over your arrays after understanding this you'll be able to fix the problems.
Bryan, I don't see the problem offhand, but what you're describing sounds like you are having an array indexing issue. (Rule of thumb, any time you think that there's something wrong with the computer causing your errors, you're mistaken.)
Two places new C programmers run into trouble with this is getting confused by 0 based indices -- an array of size 7 has indices from 0..6 -- and by not realizing that arrays are just laid out on top of one blob of memory, so an array that's [10][5][2] is really just one 100-cell piece of memory. If you make an indexing mistake, you can put things in what appear to be random places.
I'd go through the code and check what's where in smaller steps; what happens after one initialization, that sort of thing.