## math sin wave

22 posts / 0 new
Author
Message

Hi guys,

I'm looking to display a sin wave with a frequency of one hertz with 320 samples.   I have the following code but it is not working, never was great at maths.

```void draw_graph(struct ipc_buffer_object *);
void draw_graph(struct ipc_buffer_object * graph){

fillScreen(ILI9341_WHITE);

unsigned int data1, data2, i = 0;
unsigned char status = 0;

//data1 = api_buffer_accept16(graph, &status);
//data1 = api_buffer_accept16(graph, &status);

while(i < 320){

data1 = 120;
data2 = 120;

data1 += 100 * sin(2 * 3.14 * 1 * 320 * i++);
data2 += 100 * sin(2 * 3.14 * 1 * 320 * i);

drawLine(i - 1, data1, i, data2, ILI9341_RED);
}
while(true);
}```

Any pointers guys?

This topic has a solution.
Last Edited: Mon. Jan 29, 2018 - 06:52 PM

<first response deleted - apparently I'm no good at maths either>

Two thoughts:

1. make sure your sin() function expects degrees from 0.0 to 360.0, not radians or some other unit

2. you need to scale your 320 samples to 360 degrees, so take a closer look to the calculated value passed to sin().  There should probably be a (i/320)*360 scaling factor in there somewhere.

Last Edited: Mon. Jan 29, 2018 - 06:15 PM

That does not work mate.

This reply has been marked as the solution.

I don't understand what you're trying to do.

i seems to be your X-coordinate and data1 & data2 are Y coordinates.

But why calculate the same thing twice?

Why add someting to data1 and data2 ???

I would probably do something like:

```#define OFFEST 120 // const static int ? ...

for(X=0; X<230; ++X){
Y = OFFSET + 100 * sin(2 * 3.14 * 1 * 320 * X);
drawLine( X-1, Yold, X, Y, ILI9341_RED);
Yold = Y;
}
```

If I remember well, there is also a sine drawn in the UTFT example code.

Yep.

Show case at 3m50s into this video:

Edit:

So this looks more appropriate:

`        Y = OFFSET + 100 * sin(2 * 3.14 * X / 320);`

Edit 2:

First edit was crosed with Jim (below).

It should get something sensible on your screen and if you have some trouble with the math just experiment a bit.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Last Edited: Mon. Jan 29, 2018 - 06:29 PM

Trig function arguments are usually in radians. The argument range 0 to 2*pi gives you one complete period. So, for 360 samples in one period, you would do

A = sin(2*pi * i / 360) with i from 0 to 359. i = 360 will be the same as i = 0. The argument is in the form of a simple proportion.

This gives you the 360 samples, but does not specify any particular period. Usually, in a micro, this is dealt with by controlling the RATE at which i is stepped. This, in turn, is usually managed with a timer. There is also a little caveat, here. Period is measured between successive zero crossings with the same slope. Thus, it is the time between i = 0 and i = 360. This is 361 sample points. To make one cycle at a frequency, F, with 360 samples per cycle, you would need to step at a rate of F*360 through 361 samples, recognizing that i = 360 can be rolled back to i = 0.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Mon. Jan 29, 2018 - 06:26 PM

> There should probably be a (i/320)*360 scaling factor in there somewhere.

Forcing the divide of integers before the multiplies potentially loses resolution.

Something like  i * 360 / 320 (assuming the compiler works left to right) should be more reliable.

Mistrusting the compiler this should enforce good behavior ((i*360)/320).

Create the table in Excel:

https://www.avrfreaks.net/comment...

https://www.avrfreaks.net/comment...

https://www.avrfreaks.net/comment...

Top Tips:

1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...

ka7ehk wrote:
Trig function arguments are usually in radians. The argument range 0 to 2*pi gives you one complete period. So, for 360 samples in one period, you would do

`sin(2 * 3.14 * 1 * 320 * i++);`

I get that "2 * 3.14" is PI * 2 (<math.h> will likely define M_PI by the way) but what is the pointless "* 1" doing in there and even more curious what is the "* 320" doing in there.

As Jim says sin() takes a value in Radians so should be in the range 0 .. 2 * PI and so for 320 samples that should be multiplied by "i / 320" to split it into 320 fractional pieces. The multiplication in the original code is just plain wrong.

I often prefer writing a small PC program instead of a spreadsheet if algorithm complexity gets above a certain level, as in the example I gave in:

https://www.avrfreaks.net/forum/a...

Writing a dawLine() which just uses printf() to print it's parameters gives all the insight you need.

With a PC program you can just copy & paste when it works or change the "DEBUG" statement if you want to compile on different platforms.

@clawson:

The "320" is almost certainly a scale factor to scale the sine to the with of his lcd screen. And I also removed the "*1" in post #4.

But OP already marked it as solved, sow why continue?  Once you have something sensible on the LCD it's pretty easy to correct from there.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Last Edited: Tue. Jan 30, 2018 - 10:11 AM

Paulvdh wrote:
I often prefer writing a small PC program instead of a spreadsheet

Whether you prefer "PC program" or spreadsheet or whatever, the main point is to get it done once on a host system - where writing, debugging & testing are all so much easier.

Don't mess about trying to do it on the target!

https://www.avrfreaks.net/comment...

Top Tips:

1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...

awneil wrote:
Don't mess about trying to do it on the target!
But the target here is a UC3 not an AVR8 (from his other threads). I would have thought your average UC3 had no issues running a bit of FP at run time.

True.

But the issues seem to be with the OP getting his maths right - which, I think, would be more appropriately done on a PC

Top Tips:

1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...

And the same bit of program (except from drawLine) should work (or not) both on the PC than on the host .... -> c should be used on both sides

(perhaps, on the PC side, the C  should write the values to a file (redirection is trivial)  so that R, exc"el, gnuplot, matlab, python+matplotlib  can display them if one is fond of sinusoids).

Main things is that pieces of code tested on a PC should be reused on the host (other things used only to verify/display)... ond AFAIK, neither R, nor gnuplot, nor excel, nor python+matlotlib  .... can be ported on a MCU.....

Edited : even if it marked as solved, many things can make someone sad:

* what if LCd changes, and has no more 320 cols? (320 should be typed only once, to make code evolution less typo prone)

* there is a double invocation of sin; one should keep trace of the former point(x, y) and compute only the next one; draw segment; update the previous point...

* no way to display in real time ... should fill regularly the screen, with some extra timer....?

and I guess I missed many other things ....

Last Edited: Tue. Jan 30, 2018 - 10:40 AM

Yeah sure,

if you want you can write resolution independent LCD libraries if you want.

Some of the LCD vendors (Newhaven?) have probably already done that for the displays they sell or such a library might come with commercial C compilers.

http://www.hpinfotech.ro/cvavr_g...

There are also big "everything" simulators such as in proteus.

But if you're working on the hobby level and are happy with libraries such as UTFT or Adafruits' then doing some basic checks on your algorithms is usually enough.

Using a host with a propper debugger where you can step through the code is often the biggest plus.

C is a logical choise, but if you have some python skills then porting an python algorithm to C for your uC is often a small task. (Not talking about uPython here).

But als always, is a mix of using the tools you are familar with or using the best tools appropriate for the job.
I've never gotten around to learning gnuplot properly or even a spreadsheet...

Most important of all is probably to help people realise they don't have to do everything on their target (AVR or otherwise) processor.

Once that realisation has sunk in it tickles the creativity about the use of other tools.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Paulvdh wrote:
Most important of all is probably to help people realise they don't have to do everything on their target (AVR or otherwise) processor.

Once that realisation has sunk in it tickles the creativity about the use of other tools.

Excellent Point!

Top Tips:

1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...

I've never gotten around to learning gnuplot properly

Neither did I... (but I remmanded , indirectly, to a matlab using friend : octave -a matlab clone-  uses gnuplot to display curves... and to me to   quickly display curves with a C program outputting values, without ressource eating -R or python matplotlib are greedy-)

IMO, python is more difficult than C .... (unless one has thoroughly learnt it .... unlikely in a hobbyist case).

dbrion0606 wrote:
IMO, python is more difficult than C .
Really? ...

```import math
import tkinter as tk

window = tk.Tk()

window.geometry('320x240+10+10')

window.title('Sine example')

canvas = tk.Canvas(window, width=320, height=240)
canvas.pack()

for x in range(320):
y = 120 * math.sin(2 * math.pi * x / 320.0)
canvas.create_line(x, 120, x, int(y) + 120)

tk.mainloop()```

Produces:

I'd like to see that done in C or C++ in as little code !!

dbrion0606 wrote:
unlikely in a hobbyist case

Except that Python is one of the main ways to program an Rpi so after they have traded up from Arduinos I think there's gonna be a lot of hobbyists very familiar with Python.

Because of it's interactivity it is a much better "beginners language" than C. It's a bit like reverting to the old days where we probably all started out with some kind of interactive BASIC.

It's also heavily object oriented so it makes a smooth way into C++ too ;-)

And to Johan who was asking about mechanisms for writing Windows programs in another thread the above hopefully demonstrates how easy it is to throw something together in Python. What's more if you took that Python and ran it unaltered in Linux you would see the same result thought the "window decoration" (minimize, maximize, close buttons and border) may look a bit different.

Last Edited: Tue. Jan 30, 2018 - 12:08 PM

PS and yes, if you were wondering if that sine wave is upside down, it is, I forgot the position of the origin for tk.Canvas() !

Y goes DOWN the screen, not up!!

Last Edited: Tue. Jan 30, 2018 - 12:22 PM

Because I already have GNU Octave installed I searched the web for an example.

http://www.obihiro.ac.jp/~suzuki...

```x = 0:1:320;
plot (x, 120* sin( 2*pi*x/320));
```

In the plot window you can zoom, scroll, save etc.

No nothing to import, no pi to define, no custom scaling.

You just give it some function and specify the range over which to plot it and it does something intelligently with it.

It's quite the beast for mathematical stuff.

(Octave is an open source drop in script compatible version of matlab).

https://www.gnu.org/software/oct...

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Last Edited: Tue. Jan 30, 2018 - 12:44 PM

Never used interactive Basic ; used paper, pencil and eraser or punched cards -produced enough paper-.

When writing 6809 *.asm, I knew Pascal existed, might be implemented xxx km from where I lived, and I begun with peudo code - even in the last century, I needed some structured language-

I know python is taught in a methodical way in schools (but I do not think, from horrors I saw on fora, RPi users learnt methodically nor rationally).

Your example is very beautiful, wotks on cygwin (tkinter is sometimes  named Tkinter).

If one accepts to eat more ressources (worked on 500 M nanopi, 1 year ago, however-) matplotlib leads to more concise python (cf   https://balau82.wordpress.com/2011/03/26/capturing-an-analog-signal-with-arduino-and-python/

, with a trivial adaptation; btw as matplotlib is shipped with scipy, one can easily make spectral analysis ... and display it, with a succession of trivial adaptations; I could verify pythons spectra were consistent with R's ones....).

Sometimes matplotlib is used as a better -interactive exploration of images; publication - quality drawings) displayer than native pyimage/pyOCV

C++ exists in the nanopi (30% slower, cheaper than RPi) world they are shipped with OCV and pyOCv to ... manage a camera : I noticed, from https://www.learnopencv.com/face... (and many other sources from this blog) that opencv c++ sources had about the same size as python sources : as easy to understand, adapt...

There are things I can do very easily in C (my nanoPis have a man preinstalled), in R (their help is very comfortable, with ready to use examples) .

With python, on line documentation is terrible...

When, using ocv on nanoPi / RPi; one notices it is very slow; adapting the storing of mean images (from *.(x,y)ml , native ASCII way of storing to raw binary) leads to dramatic changes in execution time.... This I can do with c++ and my knowledge of c; with python, it would be more difficult...)

Thus, I decided ... to ignore/forget  python for a while and concentrate on C++ (as it was Arduino and openCV friendly)

Edited : noticed than gnuplot (piped from Octave) makes gorgeous drawings, too. It is very simple piping gnuplot from a C program, IIRC (R's default plot is ugly, and must evolve towards a nice drawing).

Last Edited: Tue. Jan 30, 2018 - 02:15 PM

Well, I looked at the way R did it and it is very easy, too)

``` pi=4.*atan(1); plot(sin(2*pi *(1:320) /320),  type='l')
```

Result is much uglier (keeps track of the formula). Wonot show it (should add more options to make it beautiful)

The fact that gnuplot (is fed by GNUoctave) and matplotlib  give the same gorgeous drawings is linked to history : octave is a matlab clone; matplotlib is meant to clone matlab's drawings.... and has the very same functionalities than matlab/octave plot.... (is used in the pyopencv world, sometimes)

Last Edited: Tue. Jan 30, 2018 - 01:10 PM

Well, i had a look at matplotlib : code is much more concise than tkinter's  -no window to create and manage- . It is less concise than R and ocrave (and one need to have X connection under gnuLinux : R diverts to a default *.pdf)

```sh-4.1\$ python
Python 2.7.3 (default, Dec 18 2012, 13:50:09)
[GCC 4.5.3] on cygwin
>>> from matplotlib import *
>>> import math
>>> for x in range(320): # Clawson's loop and formula
...     y.append (120 * math.sin(2 * math.pi * x / 320.0)) # storing into arrays is weird
...
>>> y
[0.0, 2.356043095275396, 4.711177891088234, ...
....
]
>>> import matplotlib.pyplot as plt # Balau
>>> plt.plot(y)
[<matplotlib.lines.Line2D object at 0x7dc1a60c>]
>>> plt.show()
```

shows almost exactly the same sinusoîd as Paulvdh (just some buttons were added, to store result drawing  into a file -png, tif, pdf,svg are supported- : mouse exploration is the same). "My drawing is better than yours" games  would be very irrelevant.

I bet it eats more resources than tkinter, gnuplot or even octave....)

Last Edited: Thu. Feb 1, 2018 - 01:17 PM