I'm working on an Arduino program that reads data from an anemometer and if the wind is above a certain threshold, it activates a relay. The threshold can be set in two ways:
1) The user can use two buttons to increase or decrease the threshold
2) If a certain button is held for 2 seconds, the threshold will sync with the current wind speed.
My problem is this: the increase and decrease buttons change the threshold value by +/- 0.5 km/h. But the wind speed is read with 0.1 km/h precision. So what can sometimes happen is if the current wind speed is, say, 12.2 km/h, and the sync button is held, the threshold now becomes 12.2 km/h. No problem yet...
But then if the user presses one of the increase/decrease buttons, the threshold still changes by +/- 0.5 km/h, meaning the values will increase like 12.2, 12.7, 13.2, 13.7, etc.
What I would like to have happen is for the increase/decrease buttons to put the threshold value to the nearest 0.5 multiple. So if the sync button was used, and the threshold was set to 12.2, pressing the increase button would change to 12.5, and then continue in steps of 0.5 from there.
I can think of a few ways to fix this issue, but none of them are very elegant. I want to use the simplest solution possible.
Note: I'm not including any of my code because this is more of a logic/pseudocode question. Also, this is my first forum post, so let me know if I need to change anything in my post!
EDIT: Pseudo, by request.
if increase button pressed
threshold+=0.5
if decrease button pressed
threshold-=0.5
if sync button held
threshold = current wind speed
Handle_key_press_down(key, &threshold) {
min_step = 0.5
Hysteresis = min_step*0.6 // Avoid threshold that is exactly same as the current speed
New_threshold = round_to_nearest(threshold, min_step)
If (key == up) {
New_thresh = Threshold + min_step
Else if (key == down) {
New_thresh = Threshold - min_step
Else if (key == sync) {
Wait_for_release
If release_time >= 2.0s
New_thresh = round_to_nearest(Get_current() + Hysteresis, min_step)
Else
ignore
Endif
// Insure, no matter what, threshold is within design limits.
If (New_thresh > threshold_max) New_thresh = threshold_max
If (New_thresh < threshold_min) New_thresh = threshold_min
return New_thresh
}
Sophisticated C++ solution for Arduino (grin)
#include <math.h>
// button == 1 increase, button == 0 decrease
void adjust(float& level, char button) {
float floorVal2=floor(level*2); // level*2 is equiv to level/0.5
if(fabs(floorVal2-2*level)<1e-5 ) {
// they aren't close enough to consider them equal
level=
button
? (floorVal2+1)/2 // this is equiv to ceil(level/0.5)*0.5
: floorVal2/2 // this is floor(level/0.5)*0.5
;
}
else {
level += (button ? 0.5 -0.5)
}
}
void read(float& level) {
level=MySensor::getCurrentValue();
}
Related
the gif will better explain what I'm trying to do.
Bow aim.
as you can see I can't get the arrow to follow the aim. The problem is I have the Bow and Arrow separate so the bow spawns the arrow and that's the problem I can't get the calculation of the hspeed and vspeed and gravity of the arrow to match the bow draw event of the doted aim. I will post the doted aim code and the arrow gravity/movement code the spawn code for the arrow is simple on the release of the button it spawns the arrow at the x,y position of the bow. If you need any other code I will post it. Sorry if it's not well explained.
Arrow Code:
End Step
///Check if parent still exists
if (parent != noone)
if (!instance_exists(parent))
{
parent = noone;
}
///Gravity
if (grav != 0)
{
hsp += lengthdir_x(grav, grav_dir);
vsp += lengthdir_y(grav, grav_dir);
}
///Increase gravity over time, up until a maximum amount
grav = min(grav+grav_add, grav_max);
///Limit speed
hsp = clamp(hsp, -hsp_max, hsp_max);
vsp = clamp(vsp, -vsp_max, vsp_max);
///Calculate directional speed
var sp = point_distance(0, 0, hsp, vsp);
direction = point_direction(0, 0, hsp, vsp);
Bow:
DrawEvent:
var _f_x = x;
var _f_y = y;
var _f_spd_x = draw_aim_circle_max * dcos(controler_angle)
var _f_spd_y = draw_aim_circle_max *-dsin(controler_angle)
while (!instance_place(_f_x,_f_y,objAimCircleKiller))
{
draw_sprite(sprAimCircleSmall,0,_f_x,_f_y+1);
_f_x += _f_spd_x
_f_spd_y += grav_aimCircle
_f_y += _f_spd_y;
}
Do you have some code in Arrow to slowdown the horizontal speed? It seems to stop faster than it should. Try to use a different variable to manage the horizontal speed instead of the grav var.
When calculate the x speed of the arrow, define an explicit value max speed. The arrow speed should be max speed when the sin angle is 90° and close to 0 when sin angle is 0. Then just use the arcsin function to get a value from 0/1 and multiply for the max speed.
var maxHorSpeed = 10;
var aimAngle = lengthdir_y(bow.x,bow.y,target.x,target.y);
arrow.horizontalSpeed = clamp( sin(aimAngle)*maxHorSpeed,0.2, maxHorSpeed);
I wrote a sample code to measure the brightness of LED by controlling the duty cycle of LED connected to Arduino. I want to get the range of least bright light to max bright light for a specific period of period. When i put desired_brightness = 1, the LED is emitting light at 93 lux units, its not the least brightlight. Any suggestion on how to get the least bright light?
int led = 3; // the pin that the LED is attached to
int brightness =0; // how bright the LED is
int incrementfactor = 10; // how many points to fade the LED by
int desired_brightness = 255 ;
int extra_delay = 1000;
void setup() { // declare pin 9 to be an output:
pinMode(led, OUTPUT);
analogWrite(led, desired_brightness);
}
void loop() {
analogWrite(led, desired_brightness);
brightness=brightness+incrementfactor;
if (brightness==desired_brightness) {
delay(extra_delay);
}
}
I've tailored your code a bit. The main problem was you were going to maximum brightness right away, and were never decreasing it. analogWrite() only takes values from 0 to 255. You were starting at 255 and increasing from there, so it just stayed bright. Try this instead, it's the "breathing effect" you see on so many electronics these days, and loops forever:
int ledPin = 3; // the pin that the LED is attached to
int brightness =0; // how bright the LED is
int extra_delay = 1000; // the extra delay at max
int super_delay = 5000; // super delay at min
int direction = 1; // the dimmer-brighter direction
void setup() {
pinMode(ledPin, OUTPUT);
analogWrite(ledPin, 0);
}
void loop() {
analogWrite(ledPin, brightness); // light at certain brightness
//delay(5); // wait a bit, stay at this level so we can see the effect!
delay(50); // longer delay means much slower change from bright to dim
if (direction == 1) // determine whether to go brighter or dimmer
brightness += 1;
else
brightness -= 1;
if (brightness == 255) // switch direction for next time
{
direction = -1;
delay(extra_delay); // extra delay at maximum brightness
}
if (brightness == 0) // switch direction, go brighter next time
{
direction = 1;
delay(super_delay); // super long delay at minimum brightness
}
}
This will go brighter, then dim, and repeat. The delay is very important -- you can reduce it or lengthen it, but without it, the change happens so fast you can't see it by eye, only on an oscilloscope. Hope this helps you!
EDIT:
Added a "super delay" at minimum brightness for measurement of that level.
One thing to keep in mind is that pulse-width modulation like this still gives full driving voltage from the output pin. PWM just alters the ratio of the time the pin is high vs. low. On this Aduino, it's still a voltage swinging instantly and quite rapidly between 0V and 3.3V. To get a true analog voltage from this output, one needs some circuitry to filter the highs and lows of PWM into a smoother average DC voltage. If you want to pursue that, search for "RC low-pass filter" or visit a site like this one.
I have an issue that I'm wondering if there's a simpler way to solve.
I am using Input.GetAxis(), for example, let's say Horizontal.
Holding D-> with Input.GetAxis("Horizontal") will result in the value gradually going from 0 to 1.
Releasing D-> will gradually bring it back down to 0.
Here's my problem. If I am to hold down D->, then press A<- and release D->, the value instead of gradually dropping 1 to 0, then 0 to -1, instead instantly snaps to 0 and proceeds to gradually drop to -1.
I am using this value to control my animations, and it makes them snap all ugly.
Is there a way I make the value drop gradually like I intend without much code or am I missing some settings for the animator?
float tempADFloat = playerAnim.GetFloat("ADInput");
if (_ADInput != 0)
{
playerAnim.SetFloat("ADInput", Mathf.Clamp(tempADFloat + 0.1f * _ADInput, -1f, 1f));
} else
{
if ((tempADFloat < 0.2 && tempADFloat > -0.2))
{
playerAnim.SetFloat("ADInput", 0);
} else if (tempADFloat < 0)
{
playerAnim.SetFloat("ADInput", tempADFloat + 0.1f);
} else if (tempADFloat > 0)
{
playerAnim.SetFloat("ADInput", tempADFloat - 0.1f);
}
}
playerAnim is my characters animator reference.
This way animations transition smoothly.
I use tempADFloat < 0.2 instead of tempADFloat < 0.1 because the value can't be set and checked in time. It will basically end up jumping 0.1 to 0 back and forth
I am working on a GTK+ application that uses goocanvas to display a graph on screen. I am having problems coming up with a good way to implement drag scrolling.
Currently the app saves the coordinates where the user clicked and then in a "motion-notify" signal callback, does goo_canvas_scroll_to() to the new position. The problem is that drawing is somewhat slow, and with each pixel moved by the mouse, I get the callback invoked once. This makes the drawing lag behind when dragging the graph around.
Is there a good way to do drag scrolling, so it'd appear more smooth and I could skip some of the redraws?
I was able to get something like this working once by starting a 5ms timer when the user presses the mouse button. In the timer I check where the mouse is and decide which way to scroll, including faster scrolling the closer you are to the edge. The result was very smooth scrolling, at least that's what I remember. Here the guts of it, its gtkmm/c++, but you should be able to get the gist of it:
static const int HOT_AREA = 24;
// convert distance into scroll size. The larger the
// value, the faster the scrolling.
static int accel_fn(int dist) {
if (dist > HOT_AREA)
dist = HOT_AREA;
int dif = dist / (HOT_AREA/4);
if (dif <= 0) dif = 1;
return dif;
}
bool scrollerAddin::on_timeout() {
int ptr_x, ptr_y;
o_scroller->get_pointer(ptr_x, ptr_y);
int vp_width = o_scroller->get_width();
int vp_height = o_scroller->get_height();
if (o_scroller->get_hscrollbar_visible())
vp_height -= o_scroller->get_hscrollbar()->get_height();
if (o_scroller->get_vscrollbar_visible())
vp_width -= o_scroller->get_vscrollbar()->get_width();
if (ptr_x < HOT_AREA)
scroll_left(accel_fn(HOT_AREA-ptr_x));
else if (ptr_x > vp_width - HOT_AREA)
scroll_right(accel_fn(ptr_x - (vp_width - HOT_AREA)));
if (ptr_y < HOT_AREA)
scroll_up(accel_fn(HOT_AREA - ptr_y));
else if (ptr_y > vp_height - HOT_AREA)
scroll_down(accel_fn(ptr_y - (vp_height - HOT_AREA)));
return true;
}
The scroll functions merely adjust the appropriate Adjustment object by the argument.
i want to create a game and addes a image to my game, now i want it to move down smoothly. i have a code like this:
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
pos.Y = pos.Y + 1;
base.Update(gameTime);
}
the movement works but it dont looks smooth, it looks like it jiggle. pos is a vector2 for the position in the image.
how to make it more smooth?
If you want movement to be smooth without adding a physics library you just have to factor in gameTime to your position update.
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
pos.Y = pos.Y * 100 * (float)gameTime.ElapsedGameTime.TotalSeconds;
base.Update(gameTime);
}
I don't have access to XNA + visual studio right now, but the changes I made should give you an idea of what to try out. Keep in mind the Update call happens multiple times a second so the elapsed time will be a small number so then you have to multiply it by a larger "movement" value in this case I put 100. Tweak 100 until you see the movement speed you desire.
Beanish is right, you should multiply by GameTime if you want smoothness. Physics is an overkill if you only want your animation to look smooth.
The best way I've found to do animation is by using position interpolation, for this to work you have to know the initial (you already know this) and final position of the image.
If you want to move from A to B in, say, 2 seconds, you can use the following code.
Vector2 a = new Vector2(0, 0);
Vector2 b = new Vector2(0, 100);
float elapsedTime = 0;
float duration = 2.0;
public override void Update(GameTime gameTime)
{
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
elapsedTime += dt;
if (elapsedTime > 1)
elapsedTime = 1;
float param = elapsedTime / duration;
pos = Vector2.Lerp(a, b, param);
}
The best thing about using this approach is that you can now use "easing" to make you animation look really really nice.
To do this just add a Power operation to the interpolator parameter:
pos = Vector2.Lerp(a, b, (float)Math.Pow(param /2.0, 0.5));
This will make you image slow down as it arrives to B. You can play with the exponent value (0.5) to get different results, try 2.0 for example.
Another important thing is that your image will always stop at B. If you use the Euler integration approach (your approach, adding a velocity each frame) you might have some trouble making the image stop at the right position (aka B) and it gets even worse when using 2 or 3 dimesions.
To know more about easing, check Robert Penner's Easing Equations.
First I can tell you what the problem isn't. You don't need a physics engine to have smooth movement. And changing the Update to include the ElapsedGameTime will not make a lick of difference for the smoothness (assuming you haven't changed the default of IsFixedTimestep to false). When there is a fixed timestep, ElapsedGameTime will always have the same value, it will not vary.
I don't how much you are doing in your code, but if it's too much, XNA will start skipping the Draw portion of your code, and this can definitely cause jerkiness. One way to check: in your Update method, test the value of IsRunningSlowly. Whenever it is true, XNA will skip some Draw calls.
If you are not doing anything complicated, then the culprit may be the refresh rate of your monitor. If it is set to anything other than 60Hz, you will have jerkiness. You could fix this by changing your monitor's refresh rate. Alternatively you can change the value of TargetElapsedTime to match your monitor's rate.
You should consider adding to your game a library for handling physics, as for example FarseerPhysics. By calculating the position in a per time base with physics rules applied your movements will be smooth and natural.