writing to a sound file in netlogo : or how to tune netlogo - wav

I am writing a simple synthesiser.
This is the totality of my code
turtles-own [f]
to setup
ca
file-close
file-open "tune.snd"
crt 1 [set f 100]
reset-ticks
end
to go
file-write mean [sin(2 * pi * f * ticks)] of turtles
tick
end
when I run
Repeat 44100 [go] file-close
and load the output into a sound editor at 44100 hertz I get one second of sound. All is good so far. Unfortunately, it is meant to be a 100 Hz tone but instead, it is one second of something quite a bit higher [over 16k Hz].
What am I doing wrong?

First off, this is awesome!
The problem's simple. sin in NetLogo uses degrees, not radians.

Related

Generate signals with 0.1Hz resolutions using AD9833 via Arduino Uno

I would like to generate a frequency with the resolution of 0.1Hz from the range of 0.0 up til 1000.0 Hz ( Example such as 23.1 Hz, 100.5 Hz and 999.7 Hz) I have found that using AD9833 we can generate the signal as what I was required, but the notes are a bit confusing to me.
The specification can be obtained HERE .
Need your kind assist to if we can make the Arduino code.. lets say, to generate a signal of 123.4 Hz via Serial monitor from Arduino and it displayed as it is in the oscilloscope?
Thank you.
Looking at the notes, it appears that programming this chip will be non-trivial. If you don't require frequencies all the way down to 0 Hz, this job can be done much more easily with a standard Windows sound card. (Sound cards are AC-coupled, so won't go below a few Hz.) For one example, my Daqarta software can generate frequencies (with any waveform you want) at a resolution better than 0.001 Hz. The maximum frequency will be a bit less than half the sound card's sample rate... typically 20 kHz at the default 48000 Hz sample rate.
You don't have to buy Daqarta to get this capability; the Generator function will continue to work after the trial period... free, forever.
UPDATE: You don't mention what sort of waveforms you need, but note that if you can use square waves you may be able to do the whole job with the Arduino alone. The idea is to set up a timer to produce interrupts at some desired sample rate. On each interrupt you add a step value to an accumulator, and send the MSB of the accumulator to an output pin. You control the output frequency by changing the step value. This is essentially a 1-bit version of the phase accumulator approach used by the AD9833 (and by the Daqarta Generator). The frequency resolution is controlled by the sample rate and the size of the accumulator. You can easily get much better than 0.1 Hz resolution.
Best regards,

Balancing quadcopter using Arduino

I am doing a project on self balancing quadcopter with Autonomous control. I am using Arduino Mega 2560 and MPU6050. I have obtained the roll and pitch angles from MPU6050 without the help of DMP and applied complex filter to omit the noise due to vibration.
Also configured and able to run the BLDC motors with Flysky Transmitter and receiver with the help of Arduino interrupts. Now for balancing I am focusing on only one axis (i.e. roll). I have also constructed a balancing stand for the free movement of roll axis by the motor.
For the controlling part, I am implementing PID algorithm. I tried using only the kp value so that, somehow I can balance and then move on to ki and kd term. But unfortunately, for Kp itself, the quadcopter is undergoing aggressive oscillation and is not settling at all.
Some of my queries are:
Whether a single PID loop is enough, or we have to add another?
What type of tuning method I can implement, to find the kp, ki, kd other than trial and error?
I programmed my ESC for 1000 to 2000 microseconds. My PID input angles will be within the range +/- 180. Whether I can directly set the PID output limits for range -1000 to 1000 or -180 to 180 or any other value?
The code can read from the URL https://github.com/antonkewin/quadcopter/blob/master/quadpid.ino
Since its not provided, I am assuming that:
The Loop time is atleast 4ms. (The less the better)
The sensor noise is been reduced to an acceptable level.
MPU-6050 needs gyro+accel data to be combined to get angles in degrees.
If the above points are not taken care of, it will Not balance itself.
Initially, you can get away without tuning kI. So let's focus on kP and kD:
Keep increasing Kp till it starts oscillate fast. Keep the Kp value half of that.
With kP set, start experimenting kD values, as it will try to dampen the overshoots of kP.
Fiddle around these two values, tune it for perfection.
Note, the more accurate your gyro data is, the higher you can set your kP to.

netlogo issues with generating network

when I try to generate a network it looks like this: , this happens even when I try to implement very simple code e.g.
let num_neighbors 10
create-turtles 100
layout-circle turtles (world-width / 2 - 1)
ask turtles [create-links-with n-of num_neighbors other turtles]
which works in other models (e.g. looks like this). any ideas why this might be happening?

Determine true north

I am working on an Arduino device I am building.
I have bought a GPS module and a tilt sensing compas with an accelerometer.
I wish to determine true north so that I can always point an object towards the sun.
Basically I want the device to always find true north wherever it is.
The GPS will give a position, the compass will find magnetic north. I guess the true north can be obtained during movement of the device and written to RAM then retrieved for use when the device is stationary.
But how?
Are you trying to get the most sun for your rotational solar panel? If so then you can get away with just rough position setting between East and West according to your clock (you can improve this with taking long/lat position into the account to calculate sun rise and sun set times). You will need a lot of astronomy calculations if you want to control both azimuth and elevation precisely. Arduino does not support double, and with single you will not have very accurate results (they will be enough for solar panel tracker, but not enough if you want telescope to track some sky object). My advice would be to either investigate a lot on the topic, or take a look at some open source astronomy software and extract the needed calculations from the source (if licence terms permit). Just to give you a hint, this is a small extract from PilotLogic TMoon component that you can get in CodeTyphon/Lazarus/FPC installation package found here:
procedure Sun_Position_Horizontal(date:TdateTime; longitude,latitude: extended; var elevation,azimuth: extended);
var
pos1: T_Coord;
begin
pos1 := sun_coordinate(date);
calc_horizontal(pos1,date,longitude,latitude);
end;
function sun_coordinate(date:TDateTime):t_coord;
var
l,b,r: extended;
lambda,t: extended;
begin
earth_coord(date,l,b,r);
(* convert earth coordinate to sun coordinate *)
l := l+180;
b := -b;
(* conversion to FK5 *)
t := (julian_date(date)-2451545.0)/365250.0*10;
lambda:=l+(-1.397-0.00031*t)*t;
l := l-0.09033/3600;
b := b+0.03916/3600*(cos_d(lambda)-sin_d(lambda));
(* aberration *)
l := l-20.4898/3600/r;
(* correction of nutation - is done inside calc_geocentric *)
{ calc_epsilon_phi(date,delta_phi,epsilon); }
{ l := l+delta_phi; }
(* fill result and convert to geocentric *)
result.longitude := put_in_360(l);
result.latitude := b;
result.radius := r*AU;
calc_geocentric(result,date);
end;
procedure calc_horizontal(var coord:t_coord; date:TDateTime; longitude,latitude: extended);
var
h: extended;
begin
h := put_in_360(star_time(date)-coord.rektaszension-longitude);
coord.azimuth := arctan2_d(sin_d(h), cos_d(h)*sin_d(latitude)-
tan_d(coord.declination)*cos_d(latitude));
coord.elevation := arcsin_d(sin_d(latitude)*sin_d(coord.declination)+
cos_d(latitude)*cos_d(coord.declination)*cos_d(h));
end;
If you had a case that your device is not moving after installation (which is not the case after I reread your question so you can ignore the rest of the message), then your longitude and latitude are fixed and you know them at compile time, or you can enter them manually when device is first installed. That way GPS is not needed. You can also find North once at installation time, so you don't need compass either.
Compass will get haywire when it gets near some magnetic material and will not be practical at all. You can calculate the azimuth and elevation of the sun with respect to your location. It is more practical to use some digital encoders with your system and make calculated incremental movements. A calibrate button on the arduino could be used to normalize the parameters using a standard tools. For fine tune, manual buttons could be provided for up and down movements.

Simulating a 6-faced die in Ada-2005

I have very definitively come across the 'simulating a 6-faced die' (which produces a random integer between 1 and 6, all outcomes are equally probable) in Java, Python, Ruby and Bash. However, I am yet to see a similar program in Ada. Has anyone come across one?
See Random Number Generation (LRM A.5.2) for packages to assist with doing this. Either Ada.Numerics.Float_Random for uniform random number generation (range 0.0 .. 1.0) which you can then scale on your own, or instantiate Ada.Numerics.Discrete_Random with a suitable (sub)type (works for d4, d10, d12, and d20s as well!).
You might enjoy this simulation of the children's card game of war, which uses an instance of Ada.Numerics.Discrete_Random.
subtype Card_Range is Positive range 1 .. 52;
package Any_Card is new Ada.Numerics.Discrete_Random(Card_Range);
G : Any_Card.Generator;
…
N : Card_Range := Any_Card.Random(G);
With Ada 95, a random number generator was defined as part of the standard library making it a required component of every Ada 95 compilation system.
Therefore, yes you can simulate a 6-faced die in Ada quite easily.
RossetaCode.org usually have these kind of typical programs. You can find a simple 6-faced dice implementation in Pig the dice game.
These are the relevant parts of that program for a dice implementation.
You define the wanted range in a type:
type Dice_Score is range 1 .. 6;
instantiate Ada.Numerics.Discrete_Random with your type:
with Ada.Numerics.Discrete_Random;
package RND is new Ada.Numerics.Discrete_Random(Dice_Score);
Use the instantiation to get a random value in the range:
Gen: RND.Generator;
P.Recent_Roll := RND.Random(Gen);

Resources