Forum: Mikrocontroller und Digitale Elektronik Arduino Micro char array Wert negieren


von Black D. (Gast)


Lesenswert?

Moin zusammen,
ich habe ein char array mit 400 einträgen.
1
signed char S[400]

Mit diese Zeilen laufe ich das array einmal vorwärts durch und einmal 
rückwärts.
1
if(l<400){
2
m=m+1;
3
}
4
5
if(l>400){
6
m=m-1;
7
}

beim rückwärts durchlaufen möchte ich die Einträge aber negiert haben. 
Mit
1
(-1)*S[m]
 scheint es nicht zu funktionieren

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Black D. schrieb:
> Mit diese Zeilen laufe ich das array einmal vorwärts durch und einmal
> rückwärts.
In diesen Zeilen ist gar kein Zugriff auf das Array zu sehen.

> Mit (-1)*S[m] scheint es nicht zu funktionieren
Was scheint sattdessen zu passieren? Was erwartest du von dieser Zeile 
und was erhältst du stattdessen?

Ich würde es so probieren:
S[m] = -S[m];

: Bearbeitet durch Moderator
von EAF (Gast)


Lesenswert?

Black D. schrieb:
> (-1)*S[m]

S[m]^=0xFF;

????

von Jim M. (turboj)


Lesenswert?

Black D. schrieb:
> Mit diese Zeilen laufe ich das array einmal vorwärts durch und einmal
> rückwärts. [...]

Nö, tust Du nich.

Poste lieber mal 'ne vollständige .c Datei als Anhang - kurze 
Codeschnippsel sind für Außernstehende praktisch immer unverständlich.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

EAF schrieb:
> S[m]^=0xFF;
"Invertiert" ist nicht das selbe wie "Negiert".
Stichworte: Einerkomplement und Zweierkomplement.

von Black D. (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe mal die Arduino Datei hoch geladen. Ich habe mir ein Array mit 
400 Werten erzeugt. Damit möchte ich durch mehrmaligen durchlaufen und 
invertieren eine Sinuskurve erzeugen. Klar würde das auch gehen wenn ich 
alle 1600 Stellen nehmen würde. Es kann aber auch sein dass ich 
insgesamt 8000 Stellen für meinen Sinus brauche und da ist der Speicher 
voll. Deshalb meine Idee mit der Viertelkurve. Da brauche ich ja nur 
2000 Werte.

von EAF (Gast)


Lesenswert?

EAF schrieb:
> S[m]^=0xFF

Ist natürlich Unsinn..
(sorry)

von donvido (Gast)


Lesenswert?

void setup() wird nur einmalig durchlaufen,

Black D. schrieb:
> Mit diese Zeilen laufe ich das array einmal vorwärts durch und einmal
> rückwärts.

Das ist also Quatsch

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Black D. schrieb:
> Deshalb meine Idee mit der Viertelkurve.
1
//Sinussignal
2
signed char S[400]=
Warum zum Geier nimmt man 400 Werte für einen Viertelsinus? Wenn einem 
mal klar geworden ist, dass so ein binäres Konstrukt wie ein 
Mikroprozessor viel besser mit binären Zahlen zurecht kommt, dann findet 
man vorrangig Arraygrößen in Zweierpotenzen wie z.B. ... 32, 64, 128, 
256, 512, ...

Und hier hätten 256 locker gereicht, denn selbst am Punkt mit der 
stärksten Steigung hast du immer mindestens 2 Werte: 0,0,1,1,2,2,2, ...

Dass dann dein Ausgabewert natürlich auch nur bis 100 (bzw. 99) geht ist 
natürlich auch dem Zehnfingersystem des Menschen zu verdanken. Ein 
digitales Bauteil würde hier 127 als Obergrenze und damit einem 
Wertebereich von -127..127 vorziehen (das mit -128 ist dann doch eher 
für Fortgeschrittene).

Zum Code:
1
if(l<400){
2
  m=m+1;
3
}
4
5
if(l>400 && l<800){
6
  m=m-1;
7
}
Dir ist hoffentlich schon klar, dass m hier auch mal 400 werden wird, 
dein Array aber nur Elemente von 0..399 hat?


Also 2 Schritte zur Lösung:

1. Ich würde hier über die Quadranten gehen (das tust du auch, aber eben 
umständlich):
1
int q=0;
2
int idx=0;
3
4
:
5
:
6
7
8
if (idx<399) {   // Index schon am Ende des Viertelkreises angekommen?
9
  idx=++;        // Nein: Index hochzählen
10
}
11
else {           // ja: Viertelkreis fertig -->
12
  idx=0;
13
  if (q<3) q++;  // nächsten Quadranten berechnen
14
  else     q=0;
15
}
16
17
// Wert aus Array holen und Ausgabewert berechnen
18
switch (q) {
19
   case 0: val =  S[idx];     break;
20
   case 1: val =  S[399-idx]; break;
21
   case 2: val = -S[idx];     break;
22
   case 3: val = -S[399-idx]; break;      
23
}


Und dann würde ich natürlich mit Zweierpotenzen reichen. Damit wird das 
voll simpel:
1
int q=0;
2
int idx=0;
3
4
//Sinussignal
5
signed char S[256]= {0,1,2,2,3,...  ...};
6
7
:
8
:
9
10
// Index hochzählen, einfach immer weiter...
11
idx=++;
12
13
// den aktuellen Quadranten berechnen, der steckt in den Bits 8 und 9 
14
q = (idx>>8)&0x03;       // --> diese beiden Bits auf q abbilden
15
16
// Wert abhängig vom Quadranten aus Array holen und Ausgabewert berechnen
17
switch (q) {
18
   case 0: val =  S[idx];     break;
19
   case 1: val =  S[255-idx]; break;
20
   case 2: val = -S[idx];     break;
21
   case 3: val = -S[255-idx]; break;      
22
}

: Bearbeitet durch Moderator
von Black D. (Gast)


Lesenswert?

Bei einer Frequenz von 80kHz für Timer1 brauche ich für meinen Sinus 
eine Frequenz von 50Hz. 80kHz/50Hz = 1600 Stellen für einen Sinus.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Black D. schrieb:
> Bei einer Frequenz von 80kHz für Timer1 brauche ich für meinen Sinus
> eine Frequenz von 50Hz. 80kHz/50Hz = 1600 Stellen für einen Sinus.
Lösung 1 (die "Schnellere"): Ändere doch einfach den Wert vom Timer1...

Lösung 2: (die "Bessere"): Sieh dir mal das Thema DDFS (aka. DDS) an. 
Damit kann man aus irgendeiner Frequenz irgendeine niedrigere Frequenz 
erzeugen. Der Witz ist der Akkumulator, in dem die "Mikroschritte" 
aufsummiert werden.

In dem Bild dort ganz unten ist zu sehen, wie ohne Änderung einer 
Taktfrequenz die Frequenz des Ausgabesignals geändert wird:
http://www.lothar-miller.de/s9y/categories/31-DDFS

Mein Tipp: gib dir einfach Zeit, bis du es verstanden hast. Bei mir hat 
das auch ein paar Tage gebraucht.

: Bearbeitet durch Moderator
von Black D. (Gast)


Lesenswert?

Dazu kommt dass ich für mein Dreiecksignal ja auch noch eine bestimmte 
Frequenz brauche. Die Sinusfrequenz ist wie ja schon geschrieben bei 
50Hz und die Frequenz für das Dreiecksignal liegt bei 5kHz. 80kHz/16 
Stellen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Black D. schrieb:
> Dazu kommt dass ich für mein Dreiecksignal ja auch noch eine bestimmte
> Frequenz brauche.
Als Tipp: wenn man einen Sinus per DDFS mit beliebiger Frequenz 
darstellen kann, dann kann man auch ein Dreiecksignal (das ja auch nur 
aus 4 Quadranten besteht) mit beliebiger Frequenz darstellen.

Kleiner Tipp: man braucht dazu nicht mal ein Array, denn das 
Dreieckssignal steckt schon im index-Zähler.

Mein Eindruck ist allerdings: du willst darüber nicht nachdenken und 
suchst Ausreden.

Aber kein Problem: wenn du es so machen willst, wie du es dir 
vorstellst, dann mach es so. Da kann dir keiner in die Suppe spucken, 
die du dann hinterher auszulöffeln hast.

> Die Sinusfrequenz ist wie ja schon geschrieben bei 50Hz und die Frequenz
> für das Dreiecksignal liegt bei 5kHz. 80kHz/16 Stellen.
Willst du einen Umrichter bauen?
Dann würde ich zum Verfeinern des Dreiecks aber den Zählerinhalt vom 
Timer1 auch noch verwenden, denn sonst hast du ja krasse Stufen da drin.

: Bearbeitet durch Moderator
von Axel S. (a-za-z0-9)


Lesenswert?

Black D. schrieb:
> Bei einer Frequenz von 80kHz für Timer1 brauche ich für meinen Sinus
> eine Frequenz von 50Hz. 80kHz/50Hz = 1600 Stellen für einen Sinus.

Ja. Und? Bei 40kHz vom Timer dann eben nur 800. Oder anders herum: bei 
256 Stützstellen in einem Quadranten hättest du 1024 Stützstellen für 
den ganzen Sinus und bräuchtest eine Timerfrequenz von 51.2kHz.

Die 80kHz sind doch nicht in Stein gemeißelt, oder etwa doch?

von Hartmut S. (hsemken)


Lesenswert?

Black D. schrieb:

> Mit
1
(-1)*S[m]
 scheint es nicht zu funktionieren

Die Zeile berechnet das Inverse von S[m] und returniert es.
Wenn Du das auch wieder abspeichern willst, dann musst Du es auch 
abspeichern, S[m] = (-1)*S[m] oder so.

hase

von Falk B. (falk)


Lesenswert?

Black D. schrieb:
> Moin zusammen,
> ich habe ein char array mit 400 einträgen.

Du hast es immer noch nicht verstanden. Entweder bist du schwer von 
Begriff oder autistisch. Ich tippe auf letzteres.

Beitrag "Re: Arduino Micro SPWM"

>Dazu kommt dass ich für mein Dreiecksignal ja auch noch eine bestimmte
>Frequenz brauche. Die Sinusfrequenz ist wie ja schon geschrieben bei
>50Hz und die Frequenz für das Dreiecksignal liegt bei 5kHz. 80kHz/16
>Stellen.

Nö, brauchst du nicht. Aber wem sage ich das?

von Falk B. (falk)


Lesenswert?

Hartmut S. schrieb:
> Die Zeile berechnet das Inverse von S[m] und returniert es.

Soso, returniert es. Mann O Mann, was ist mit dieser Welt los, nur noch 
sprachbehinderte Menschen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.