i learned to calculate average velocity between two intervals. For the below table i calculated average velocity by calulating velocitties at 10 and 15 by information given and average of both them will be the average velocity at 12.5sec. But most calculate average velocity by first method. Both answers will be completely different.
I want to understand the assumptions and when to use which method.
Time (s)
Distance (m)
Velocity (m/s)
0
0
0
5
55
11
10
120
12
15
200
13.33
20
270
13.5
FIRST METHOD
average velocity = (202m - 122m)/(15s - 10s)
average velocity = 80m/5s
average velocity = 16m/shere
SECOND METHOD
velocity = (122 m)/(10 s) = 12.2m/s
velocity = (202 m)/(15 s) = 13.4667 m/s
average velocity = (13.4667 m/s + 12.2 m/s)/2
average velocity = 12.8333 m/s
I used STM32F407VG to create a 30 khz sine wave. Timer settings are; Prescaler = 2-1, ARR = 1, also the clock is 84 Mhz(the clock which runs DAC).
I wrote a function called generate_sin();
#define SINE_ARY_SIZE (360)
const int MAX_SINE_DEGERI = 4095; // max_sine_value
const double BASLANGIC_NOKTASI = 2047.5; //starting point
uint32_t sine_ary[SINE_ARY_SIZE];
void generate_sine(){
for (int i = 0; i < SINE_ARY_SIZE; i++){
double deger = (sin(i*M_PI*360/180/SINE_ARY_SIZE) * BASLANGIC_NOKTASI) + BASLANGIC_NOKTASI; //double value
sine_ary[i] = (uint32_t)deger; // value
}
This is the function which creates sine wave. I used HAL DMA to send DAC output variables.
HAL_TIM_Base_Start(&htim2);
generate_sine();
HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, sine_ary, SINE_ARY_SIZE, DAC_ALIGN_12B_R);
These are the codes i used to do what i want. But im having a trouble to change frequency without changing prescaler or ARR.
So here is my question. Can i change frequency without changing timer settings ? For example i want to use buttons and whenever i push button i want my frequency to change.
The generate_sine function will give you one period of a sine wave which has SINE_ARY_SIZE of samples.
To increase the frequency you need to make the period shorter (for 2x frequency, you would have half the number of samples per period). So you should calculate the array for smaller SINE_ARY_SIZE (which will fill just part of the original buffer with a shorter sine wave) and also put this smaller value in the HAL_DAC_Start_DMA function.
Decreasing the frequency will require making the array longer.
You should declare the sine_ary with a maximum length that you will need (for lowest frequency). Make sure it fits in RAM.
#define MAXIMUM_ARRAY_LENGTH 360
uint32_t usedArrayLength = 180;
const double amplitude = 2047.5;
uint32_t sine_ary[MAXIMUM_ARRAY_LENGTH];
void generate_sine(){
for (int i = 0; i < usedArrayLength; i++){
double value = (sin(i*M_PI*2/usedArrayLength) * amplitude) + amplitude;
sine_ary[i] = (uint32_t)value; // value
}
This will have two times higher frequency than the original code, because it only has 180 samples per period, compared to 360.
Start it using
HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, sine_ary, usedArrayLength, DAC_ALIGN_12B_R);
To change the frequency, stop DAC, change the value of usedArrayLength (smaller value means higher frequency, must be less or equal to MAXIMUM_ARRAY_LENGTH). Then call the generate_sine function and start the DAC again by the same function (that now uses new usedArrayLength).
Frequency will be: Clock/prescaler/ARR/usedArrayLength
Also, you should use uint16_t for the array (values are from 0 to 4095, the DAC is 12bit I suppose) and DMA should be set to Half-word (2 bytes per value).
Is it normal to have very low FPS (~7fps to ~10fps) with Sprite Kit using the code below?
Use case:
I'm drawing just lines from bottom to top (1024 * 64 lines). I have some delta value that determines the positions of a single line for every frame. These lines represent my CGPath, which is assigned to the SKShapeNode every frame. Nothing else. I'm wondering about the performance of SpriteKit (or maybe of Swift).
Do you have any suggestions to improve the performance?
Screen:
Code:
import UIKit
import SpriteKit
class SKViewController: UIViewController {
#IBOutlet weak var skView: SKView!
var scene: SKScene!
var lines: SKShapeNode!
let N: Int = 1024 * 64
var delta: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
scene = SKScene(size: skView.bounds.size)
scene.delegate = self
skView.showsFPS = true
skView.showsDrawCount = true
skView.presentScene(scene)
lines = SKShapeNode()
lines.lineWidth = 1
lines.strokeColor = .white
scene.addChild(lines)
}
}
extension SKViewController: SKSceneDelegate {
func update(_ currentTime: TimeInterval, for scene: SKScene) {
let w: CGFloat = scene.size.width
let offset: CGFloat = w / CGFloat(N)
let path = UIBezierPath()
for i in 0 ..< N { // N -> 1024 * 64 -> 65536
let x1: CGFloat = CGFloat(i) * offset
let x2: CGFloat = x1
let y1: CGFloat = 0
let y2: CGFloat = CGFloat(delta)
path.move(to: CGPoint(x: x1, y: y1))
path.addLine(to: CGPoint(x: x2, y: y2))
}
lines.path = path.cgPath
// Updating delta to simulate the changes
//
if delta > 100 {
delta = 0
}
delta += 1
}
}
Thanks and Best regards,
Aiba ^_^
CPU
65536 is a rather large number. Telling the CPU to comprehend this many loops will always result in slowness. For example, even if I make a test Command Line project that only measures the time it takes to run an empty loop:
while true {
let date = Date().timeIntervalSince1970
for _ in 1...65536 {}
let date2 = Date().timeIntervalSince1970
print(1 / (date2 - date))
}
It will result in ~17 fps. I haven't even applied the CGPath, and it's already appreciably slow.
Dispatch Queue
If you want to keep your game at 60fps, but your rendering of specifically your CGPath may be still slow, you can use a DispatchQueue.
var rendering: Bool = false // remember to make this one an instance value
while true {
let date = Date().timeIntervalSince1970
if !rendering {
rendering = true
let foo = DispatchQueue(label: "Run The Loop")
foo.async {
for _ in 1...65536 {}
let date2 = Date().timeIntervalSince1970
print("Render", 1 / (date2 - date))
}
rendering = false
}
}
This retains a natural 60fps experience, and you can update other objects, however, the rendering of your SKShapeNode object is still quite slow.
GPU
If you'd like to speed up the rendering, I would recommend looking into running it on the GPU instead of the CPU. The GPU (Graphics Processing Unit) is much better fitted for this, and can handle huge loops without disturbing gameplay. This may require you to program it as an SKShader, in which there are tutorials for.
Check the number of subdivisions
No iOS device has a screen width over 3000 pixels or 1500 points (retina screens have logical points and physical pixels where a point is equivalent to 2 or 3 pixels depending on the scale factor; iOS works with points, but you have to also remember pixels), and the ones that even come close are those with the biggest screens (iPad Pro 12.9 and iPhone Pro Max) in landscape mode.
A typical device in portrait orientation will be less than 500 points and 1500 pixels wide.
You are dividing this width into 65536 parts, and will end up with pixel (not even point) coordinates like 0.00, 0.05, 0.10, 0.15, ..., 0.85, which will actually refer to the same pixel twenty times (my result, rounded up, in an iPhone simulator).
Your code draws twenty to sixty lines in the exact same physical position, on top of each other! Why do that? If you set N to w and use 1.0 for offset, you'll have the same visible result at 60 FPS.
Reconsider the approach
The implementation will still have some drawbacks, though, even if you greatly reduce the amount of work to be done per frame. It's not recommended to advance animation frames in update(_:) since you get no guarantees on the FPS, and you usually want your animation to follow a set schedule, i.e. complete in 1 second rather than 60 frames. (Should the FPS drop to, say, 10, a 60-frame animation would complete in 6 seconds, whereas a 1-second animation would still finish in 1 second, but at a lower frame rate, i.e. skipping frames.)
Visibly, what your animation does is draw a rectangle on the screen whose width fills the screen, and whose height increases from 0 to 100 points. I'd say, a more "standard" way of achieving this would be something like this:
let sprite = SKSpriteNode(color: .white, size: CGSize(width: scene.size.width, height: 100.0))
sprite.yScale = 0.0
scene.addChild(sprite)
sprite.run(SKAction.repeatForever(SKAction.sequence([
SKAction.scaleY(to: 1.0, duration: 2),
SKAction.scaleY(to: 0.0, duration: 0.0)
])))
Note that I used SKSpriteNode because SKShapeNode is said to suffer from bugs and performance issues, although people have reported some improvements in the past few years.
But if you do insist on redrawing the entire texture of your sprite every frame due to some specific need, that may indeed be something for custom shaders… But those require learning a whole new approach, not to mention a new programming language.
Your shader would be executed on the GPU for each pixel. I repeat: the code would be executed for each single pixel – a radical departure from the world of SpriteKit.
The shader would access a bunch of values to work with, such a normalized set of coordinates (between (0.0,0.0) and (1.0,1.0) in a variable called v_tex_coord) and a system time (seconds elapsed since the shader has been running) in u_time, and it would need to determine what color value the pixel in question would need to be – and set it by storing the value in the variable gl_FragColor.
It could be something like this:
void main() {
// default to a black color, or a three-dimensional vector v3(0.0, 0.0, 0.0):
vec3 color = vec3(0.0);
// take the fraction part of the time in seconds;
// this value will go from 0.0 to 0.9999… every second, then drop back to 0.0.
// use this to determine the relative height of the area we want to paint white:
float height = fract(u_time);
// check if the current pixel is below the height of the white area:
if (v_tex_coord.y < height) {
// if so, set it to white (a three-dimensional vector v3(1.0, 1.0, 1.0)):
color = vec3(1.0);
}
gl_FragColor = vec4(color,1.0); // the fourth dimension is the alpha
}
Put this in a file called shader.fsh, create a full-screen sprite mySprite, and assign the shader to it:
mySprite.shader = SKShader.init(fileNamed: "shader.fsh")
Once you display the sprite, its shader will take care of all of the rendering. Note, however, that your sprite will lose some SpriteKit functionalities as a result.
I was doing some work using the CoreBluetooth API and ran into a problem. All of the places I have looked, they say that to convert RSSI (Signal Strength of Bluetooth), you must do things like:
Distance = 10 ^ ((Measured Power – RSSI)/(10 * N))
And:
var txPower = -59 //hard coded power value. Usually ranges between -59 to -65
if (rssi == 0) {
return -1.0;
}
var ratio = rssi*1.0/txPower;
if (ratio < 1.0) {
return Math.pow(ratio,10);
}
else {
var distance = (0.89976)*Math.pow(ratio,7.7095) + 0.111;
return distance;
}
I have tried all of the above and everything I could find. None of it gets me the accurate measurements from about 0.5 meters to around 5 - 7 meters of distance between.
My code to do so is making both phones using the app as a central and peripheral Bluetooth and in my didDiscoverPeripheral callback from CentralManager, I get the RSSI - which I want to convert to a distance (meter, feet).
Along with that:
I also need to find out how to get the Measured Power (RSSI Strength at 1 meter) of iPhones as it would really help in the accurate calculations.
Also, what does environmental factor mean in terms of Bluetooth? What do the different environmental factors mean (which have the range of 2-4). Is there a way to change or increase the Broadcasting Power value of the Apple Device?
Basically, I am looking for an accurate RSSI to distance formula which works from distances from 0.5 meter to 5-7 meters
Thank you so much!
This is what is a common solution:
pow(10, ((-56-Double(rssi))/(10*2)))*3.2808
It was good for most distances but got very inaccurate as you get close or too far, so I ended up using bins kind of like Apple's iBeacons (Unknown, Far, Near, Immediate). If the raw RSSI is less than -80, then it is far, if it is more than -50, then it is immediate, and if it is between those two, it is near. This solution worked for me.
I have a servo motor, and this servo motor I would like to make it follow a "motion pattern" as closely as possible, and use the same value for acceleration and deceleration.
The attach picture illustrates the "motion pattern" (Y = velocity, X = Time)
motion pattern:
accelerates 0m/s to 0.100m/s.
constant velocity 0.100m/s for 4 sec.
decelerates to negative ?m/s.
accelerates to 0m/s, and motor position = 0.
How can i calculate the acceleration and deceleration?
What i have tried so far is:
Time = (total time - constant velocity time) 10 - 4 = 6sec.
Distances = (total distances - constant velocity distances ) 1 - 0.4 = 0.6meter.
acceleration = (2 * distances / (time^2) 2 * 0.6 / sqr(6) = 0.0333m/s.
But with this acceleration it over shoots in the negative direction by 500mm.
Take a look at the PLC Open motion function blocks, for example the MC_MoveRelative and the MC_MoveContinuesRelative block:
(Beckhoff documentation)
As Sergey already stated you can use those blocks to create a motion profile by entering all the parameters you need and integrating the blocks in a step chain.