How to implement the sin() function

Issue #491 resolved
yx feng created an issue

Hi John, how do you implement the sin() function in MicroBlocks?

Comments (20)

  1. John Maloney repo owner

    MicroBlocks has a sine function in the miscPrimitives library. Here is the comment:

    // Returns the sine of the given angle * 2^14 (i.e. a fixed point integer with 13 bits of
    // fraction). The input is the angle in hundreths of a degree (e.g. 4500 means 45 degrees).
    
  2. John Maloney repo owner

    Yep, that's it.

    The input is an angle in hundredths of a degree. For example, 90 degrees is 9000. The result is an integer where the fractional part is in the lower 14 bits. You typically multiply something by this and then "normalize" the final result by shifting right by 14.

    You can compute cosine by adding 9000 (90 degrees) to the input angle.

    For an example of how to use this block, look at the code for the "go to x _ y _" block in the Turtle library.

  3. yx feng reporter

    Hello John, I've recently been working on a project that requires decimals to the last 14, and since MicroBlocks can't return decimals, I've tried zooming in and out, but it's causing problems with my project, so what do you suggest?

  4. John Maloney repo owner

    MicroBlocks does not currently support floating point numbers because they would slow MicroBlocks down -- not only when when floats were were used but all math operations would be slower because they would have to check to see if any of the operands were floats. And floats are not required for most microcontroller projects: MicroBlocks has gotten through it's first seven years without floats.

    However, fractional values (i.e. decimal numbers) are required for certain calculations.

    One approach is to use "fixed point" math: scale the number by some factor (e.g. 1000 or 2^14), and then divide by that factor to get an integer result. That is what we did for the Turtle library.

    Another approach is to add a primitive function to the virtual machine to do the calculation. That is what we did to implement a function to convert air pressure changes to altitude changes.

    Can you say a bit more about your project? If there is just one calculation you need -- like the air pressure to altitude calculation -- and that calculation might be useful to others then we could consider adding it to the virtual machine.

  5. yx feng reporter

    It is a project about controlling toio in MicroBlocks, which is based on wenjie bluetooth client, ESP 32 motherboard can be used as a host to control toio through bluetooth signal, because toio needs very accurate digital calculation, otherwise it is easy to deviate.
    This is the introduction of toio
    This is the realization of a function of Snap!

  6. John Maloney repo owner

    Thanks for sharing the Snap! code. It is helpful.

    This code be implemented fairly easily in MicroBlocks using the sine primitive. However, you need to implement the behavior in a somewhat different way because the Snap! code is working with angles in radians and the MicroBlocks sine function uses degrees. However, it appears that the coreCube's direction is in degrees, so things will actually be simpler in MicroBlocks.

    I'm looking at the code in the yellow comment box. The first part of that code figures out the difference between the current direction and the desired new direction and it makes sure that difference is between -180 and 180 degrees. That is, if the angle difference is less than -180 degrees it adds 360 and if it is over 180 degrees it subtracts 360.

    The next part of the code computes the turn speed. If the absolute value of the angle difference is less than 90 degrees, then it sets outSpeed to speed times the sine of the angle difference. Since the sine function gets smaller as it approaches zero, that means that outSpeed will also get smaller as the angle difference get close to zero. This makes the motor slow down as it gets closer to the desired direction. The sine function is also negative for angles between -90 and 0 and positive between 0 an 90; that makes the motor turn in the proper direction.

    If the absolute value of the angle difference is greater than 90, it sets outSpeed to speed. In other words, the motor turns at the maximum speed until it is within +/- 90 degrees of the desired direction, then it starts to slow down by scaling by the sine of the angle difference.

    Does that explanation make sense? If so, you should be able to implement this in MicroBlocks using angles in degrees (which are easier to think about than radians). If you're not sure exactly how to do the part that scales by the sine, post your MicroBlocks code here and I can help.

  7. John Maloney repo owner

    Try this:

    scriptImage5521529.png

    Note: If you download the script image (.png file), you can drag it onto your MicroBlocks window to add it to your project.

  8. John Maloney repo owner

    I don't see anything obviously wrong. You'll need to test and debug your MicroBlocks code one step at a time with the actual robot.

    The first thing I would check is that the _toio_rawDirection block is actually returning the actual robot's direction. You could try graphing that as you manually turn the robot around. You should see numbers that reflect the angle in degrees. The range of values could be 0 to 360, -180 to 180, or maybe even -360 to 360. In any case, If you turn the robot 90 degrees, the number returned by _toio_rawDirection should change by 90.

    Once _toio_rawDirection is working, I would _toio1_isCloseToTargetDirection. That should be true if the direction parameter is within 8 degrees of _toio_rawDirection. If that block fails to return true when it is close to the desired direction, the motor will continue to turn.

    In other words, test separate pieces of code independently to make sure each one is working. Eventually, you will find the the code that isn't working as it should be, Once you do, the problem is will probably be very simple and easy to fix.You just need to become a clever detective and track down the misbehaving code.

    Good luck!

  9. yx feng reporter

    Thank you very much for your patience, the problem has been solved almost successfully, thank you very much!

  10. John Maloney repo owner

    That is great to hear! You must have done some good debugging work. Congratulations!

  11. yx feng reporter

    Hi John, I would like to ask your question again, now the motor can be stopped at speeds under 20, but over 30 it can't be stopped or needs to be rotated multiple times, is OutSpeed affecting this?

  12. John Maloney repo owner

    I'm not sure what's going on.

    Does it fail with all desired directions or only with directions in a certain range (e.g. over 180 degrees)?

    One possibility is that the motor is overshooting. However, in that case I would expect it to change direction and come back toward the desired direction, not continue around the entire circle.

    Some other things to check:

    1. Does _toio1_isCloseToTargetDirection return true when the robot is within 8 degrees of the desired direction? Does it do that for all directions? Try it for for a number of directions around the circle such as 0 45, 90, 135, 180, 225, 270, and 315.

    2. Does _toio_rawDirection work for all angles? Does it always return a number in the expected range (e.g. 0 to 360)?

    Time for some more detective work!

  13. xixicarry

    After testing, it seems to be an issue of motor overshooting. After introducing a deceleration mechanism, the problem appears to be resolved.

  14. Log in to comment