Forum: Mikrocontroller und Digitale Elektronik [AVR] Modulo funktioniert nicht richtig


von Andre G. (andgst01)


Lesenswert?

Schönen Samstag Nachmittag,

ich habe gerade ein kleines Problem und komme irgendwie nicht weiter.

Irgendwie funktioniert modulo nicht so wie es soll.
Weder mit dem a % b noch "von Hand ausprogrammiert" ( damit meine ich 
a-(b*(a/b))   ).

Bei a < b funktioniert alles.
Sobald a > b ist funktioniert es nicht mehr, ich bekomme nur noch 0 als 
Ergebniss.

a ist ein uint16_t und b ist ein uint8_t.

Ich verwende AtmelStudio 6 und einen AtMega8.

Ich wäre um jede Hilfe dankbar.

von C-hater (c-hater)


Lesenswert?

Andre G. schrieb:

> Irgendwie funktioniert modulo nicht so wie es soll.

Da es seit Jahrzehnten bei allen außer dir funktioniert, wirst wohl DU 
etwas falsch gemacht haben.

Als zeig' ein konkretes Minimalprogramm, was das "Problem" für alle 
nachvollziehbar macht.

: Wiederhergestellt durch Moderator
von Andre G. (andgst01)


Angehängte Dateien:

Lesenswert?

Wie gewünscht, Code im Anhang.

Ihr werde nur nicht viel damit anfangen können, die Ausgabe erfolgt über 
4 doppelte Siebensegment Module.
Die Module haben je zwei gemeinsame Anoden (eine für die linke und eine 
für die rechte Stelle), die Segment-Kathoden sind alle 
zusammengeschlossen und gehen über Vorwiderstände direkt auf den µC.
Die gemeinsamen Anoden gehen direkt auf den µC.

Ja, das könnte man auch eleganter lösen aber darum geht es jetzt nicht, 
es geht mir nur um die modulo Sache in Zeile 429.
Ja, die Funktion "ReturnDigitFromNumber" ist noch nicht fertig, ich 
wollte erstmal nur die Einerstelle ausgeben, dann wenn das klappt auch 
noch die Zehnerstelle und so weiter.

von Dirk B. (dirkb2)


Lesenswert?

Das ist kein Minimalprogramm.

BTW: wenn du sowas wie Variable1, variable2, variable3, … hast, möchtest 
du ein Array nehmen

: Bearbeitet durch User
von Andre G. (andgst01)


Lesenswert?

Dirk B. schrieb:
> Das ist kein Minimalprogramm.

Wie schon gesagt, von Relevanz ist nur "uint8_t Digit1 = (Number % 10);" 
in der Zeile 429.

von C-hater (c-hater)


Lesenswert?

Andre G. schrieb:
> Wie gewünscht, Code im Anhang.

Nein, das ist ganz und garnicht "wie gewünscht". Das ist erstens kein 
Minimalprogramm und zweitens...

> Ihr werde nur nicht viel damit anfangen können, die Ausgabe erfolgt über
> 4 doppelte Siebensegment Module.

...auch nicht problemlos für jeden nachvollziehbar. Den Grund nennst du 
ja bereits selber: Es ist eine konkrete Hardware nötig, um das Problem 
überhaupt erkennen zu können. Was doch sehr stark dafür spricht, dass 
nicht die Modulofunktion an sich das Problem sein kann, sondern nur 
deine Verwendung selbiger im Kontext deiner Anwendung falsch ist.

: Wiederhergestellt durch Moderator
von Andre G. (andgst01)


Lesenswert?

Ok.

Ich wollte mit dem modulo eine große Zahl in einzelne Ziffern aufteilen 
um diese einzeln auf den jeweiligen 7 Segmentanzeigen darstellen zu 
können.

Das Darstellen von einzelenn Ziffern (0 bis 9) funktioniert, aber wenn 
ich von einer größeren Zahl die Einerstelle "auslesen" will dann 
funktioniert das nicht.

Um die Einerstelle von z.B. 12345 zu bekommen kann man doch 12345%10 
nehmen, oder?
Das würde 5 entsprechen richtig?
Modulo ist doch "der Rest der Division" (vereinfacht gesagt).

Oder habe ich das was falsch verstanden?

von S. L. (sldt)


Lesenswert?

Stimmt diese Abfrage in 423..427?

von Yalu X. (yalu) (Moderator)


Lesenswert?

S. L. schrieb:
> Stimmt diese Abfrage in 423..427?

Ist mir auch gerade aufgefallen. Da sollte wohl ein > stehen.

von Andre G. (andgst01)


Lesenswert?

Yalu X. schrieb:
> S. L. schrieb:
>> Stimmt diese Abfrage in 423..427?
>
> Ist mir auch gerade aufgefallen. Da sollte wohl ein > stehen.

Danke!
DANKE!!1

Das gerichtet und es läuft!

Also funktioniert % einwandfrei, nur der "Rest" drumherum.

Bei einem "Minimalbeispiel" wo das Ergebniss von der Modulo-Operation 
direkt z.B. über UART ausgegeben wird oder einfach direkt auf einen PORT 
wäre das nicht aufgefallen.

Eine Nacht drüber schlafen und DEN GANZEN CODE ansehen hätte in dem Fall 
geholfen.

Entschuldigung dass ich eure Zeit hier mit meiner Inkompetenz 
verschwendet habe.

von Rahul D. (rahul)


Lesenswert?

Andre G. schrieb:
> Bei einem "Minimalbeispiel" wo das Ergebniss von der Modulo-Operation
> direkt z.B. über UART ausgegeben wird oder einfach direkt auf einen PORT
> wäre das nicht aufgefallen.

Man hätte festgestellt, dass das Ergbnis deiner Fehleranalyse falsch 
war.
Dann hätte man weiter suchen müssen.

von C-hater (c-hater)


Lesenswert?

Andre G. schrieb:

> Bei einem "Minimalbeispiel" wo das Ergebniss von der Modulo-Operation
> direkt z.B. über UART ausgegeben wird oder einfach direkt auf einen PORT
> wäre das nicht aufgefallen.

Das hätte immerhin gezeigt, dass Modulo funktioniert. Du also de facto 
den Fehler an der falschen Stelle suchst...

> Entschuldigung dass ich eure Zeit hier mit meiner Inkompetenz
> verschwendet habe.

Es gibt schlimmeres. Du hast immerhin erkannt, dass der Fehler bei dir 
lag (und mit Modulo rein garnix zu schaffen hatte).

Nicht jedem gelingt es, so mit eigenen Fehlern umzugehen. Insofern 
besteht zumindest Hoffnung...

: Wiederhergestellt durch Moderator
von S. L. (sldt)


Lesenswert?

an Andre G.:

Sie sollten es positiv sehen:
> Das gerichtet und es läuft!

Offenbar war nur dieser eine Fehler im Programm.

von Peter D. (peda)


Lesenswert?

Bravo.
Du hast erfolgreich widerstanden, eines der tausenden Beispiele im Web 
anzuschauen, wie andere eine 8-stellige Anzeige multiplexen. 500 Zeilen 
hat bestimmt keiner geschafft.

Das mit den Anoden direkt an den IO-Pins solltest Du nochmal überdenken.
Als Operating Conditionen werden für den ATmega8 max 20mA angegeben. Bei 
7 Segmenten sind also max 2,8mA zulässig.
8 Digits multiplexen bedeutet, sie leuchten nur 12,5% der Zeit.
Das ergibt dann effektiv 0,35mA je LED, dürfte also recht dunkel sein.
Daß LEDs nie direkt an Ports gelegt werden dürfen, sondern immer einen 
Vorwiderstand zur Strombegrenzung benötigen, setze ich mal voraus.

von Joe L. (joelisa)


Lesenswert?

Andre G. schrieb:
> Ich wollte mit dem modulo eine große Zahl in einzelne Ziffern aufteilen
> um diese einzeln auf den jeweiligen 7 Segmentanzeigen darstellen zu
> können.

Wieso das Rad nochmal neu erfinden - dazu die 5-eckige Form? printf() 
und Konsorten sind keine Option?

just my 2ct

von Stefan F. (Gast)


Lesenswert?

Joe L. schrieb:
> printf() und Konsorten sind keine Option?

Wahrscheinlich hat er sich gedacht: printf() braucht 1,5 kB Flash, das 
ist gar nicht gut. Und dann hat er 1,4 kB selbst programmiert, um das 
"Problem" zu umgehen.

von Christian (christiankpunkt)


Lesenswert?

Geht auch mit sehr viel weniger Speicher:
1
#include <stdio.h>
2
#include <stdint.h>
3
typedef uint8_t uint8;
4
typedef uint16_t uint16;
5
6
uint8 toDigits(uint16 number, uint8* digits) {
7
  uint8 ret = 0;
8
  do {
9
    digits[ret] = number%10;
10
    ret++;
11
  } while((number = number/10) > 0);
12
  return ret;
13
}
14
15
void main(void) {
16
  uint16 number = (uint16)54321;
17
  uint8 digits[5];
18
  
19
  uint8 count = toDigits(number, digits);
20
  
21
  for (uint8 i = count; i > 0; i--) {
22
    printf("%c", '0'+ digits[i-1]);
23
  }
24
  printf("\n");
25
}
Die printf Ausgabe ist nur zu Kontrolle, auf einem µC versuche ich 
printf bzw. sprintf zu vermeiden.

: Bearbeitet durch User
von Joe L. (joelisa)


Lesenswert?

Stefan F. schrieb:
> Wahrscheinlich hat er sich gedacht: printf() braucht 1,5 kB Flash, das
> ist gar nicht gut. Und dann hat er 1,4 kB selbst programmiert, um das
> "Problem" zu umgehen.

Was soll ich darauf antworten? Ihr habt natürlich alle recht ...

Aber wie wärs zwischendurch mal mit "The Zen of Python" - eine Sammlung 
von 19 "Leitprinzipien" zum Schreiben von Computerprogrammen, nicht nur 
in Python? Der Software-Ingenieur Tim Peters formulierte diese 
Leitprinzipien und veröffentlichte sie 1999 auf der Python-Mailingliste.

[https://mail.python.org/pipermail/python-list/1999-June/001951.html]

Nicht, dass ich Python sonderlich mag, aber offensichtlich werden diese 
Prinzipien in manchen Kreisen also so wichtig angesehen, dass (moderne) 
Python-Interpreter auf

>> import this

antworten mit:

>> [...]
>> Beautiful is better than ugly.
>> Explicit is better than implicit.
>> Simple is better than complex.
>> Complex is better than complicated.
>> Flat is better than nested.
>> Sparse is better than dense.
>> Readability counts.
>> [...]

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Wenn man keinen Debugger verwenden kann, bietet sich eine serielle 
Schnittstelle an, auf der man mit printf() den Inhalt von Variablen 
ausgeben kann.

Bei Arduino gehört das ja schon zur Grundausstattung*. Für Projekte ohne 
Framework hilft meine Vorlage zur Anregung: 
http://stefanfrings.de/avr_hello_world/index.html

Die Soft-Serial Version (in HelloTiny) eignet sich auch gut für Fälle, 
wo die seriellen Ports des Mikrocontrollers schon alle belegt sind. Eine 
Ausgabe auf einem einzelnen freien I/O Pin lässt sich fast immer leicht 
hinzufügen.

*) allerdings mit Serial.print()

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Macht villeicht Spaß, das Rad immer wieder neu zu erfinden, aber 
Umwandlung in Dezimalstring gibt's doch schon:
1
#include <stdint.h>
2
#include <stdlib.h>
3
4
void ausgabe_string (const char*);
5
6
void ausgabe_u16 (uint16_t n)
7
{
8
    static char str[6];
9
    ausgabe_string (utoa (n, str, 10));
10
}
11
12
int main (void)
13
{
14
    ausgabe_u16 (1234);
15
    ausgabe_u16 (0);
16
}

https://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#gad50d835af7e358518fd100179732e948

von Andre G. (andgst01)


Lesenswert?

Also die "große Zahl" in einen String umwandlen und dann einfach per 
index (ein String ist ja ein char array) oder Pointer auf die gewünschte 
Stelle zugreifen?
Clever!

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.