Forum: Compiler & IDEs Möglichst kleinen Hash erzeugen?


von Holger K. (zaldo)


Lesenswert?

Tach zusammen,

oh mann, da habe ich mir für mein Anfängerprojekt ja was ausgesucht. Auf 
Basis von einem Mega32 baue ich zur Zeit einen Kabeltester (Ich versuche 
es zumindest), der mir bis zu 31adrige Kabel durchohmt und auch 
Vertauschungen und Kurzschlüsse untereinander erkennt. Dazu schalte ich 
die einzelnen Adern über je zwei Analogmultiplexer/Demultiplexer der 
Reihe nach auf zwei AD Wandler des Megas. Das funktioniert soweit, auch 
wenn die Auflösung im niedrigen Ohmbereich mangels zusätzlicher 
Verstärker und dank der durch die Muxer stark begrenzten Prüfstroms 
nicht besonders gut ist. Aber ich möchte ja auch nicht den exakten 
Ohmwert bestimmen, sondern lediglich auf Schwankungen achten 
(Kabelbruch).

(Anm. Es sind ja eigentlich 32 Kanäle, aber einen benutze ich zur 
Temperaturkompensation)

Zu Beginn des Zyklus erfasse ich zunächst die Verschaltung des Kabels, 
indem ich in zwei verschachtelten Schleifen einmal alle Kombinationen 
abfrage. Dabei wird nur geprüft "Verbindung Ja oder Nein". Für das 
Ergebnis setze ich in einem uint_32 Array das der ensprechenden Leitung 
zugeordnete Bit, falls eine Verbindung besteht. Das befüllte Array sähe 
also etwa so aus
1
matrix[n]=  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
2
matrix[n+1]=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0
3
matrix[n+2]=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0
4
...

wobei n die "Stellung" des Sendemuxers ist und die Position des zu 
setzenden Bits im die Stellung des Empfangsmuxers wiederspiegelt.

Nun kam mir in den Sinn, es wäre ganz schön wenn ich im EEprom 
Kabeltypen ablegen könnte, und der Tester könnte mir vorschlagen, 
welches Kabel er erkannt hat. Für ein 128 Byte Array (Plus 
Beschreibungstext) ist aber das 1024 Byte EEprom recht eng und damit zu 
der Stelle wo ich nach eurer Meinung fragen möchte: Könnte aus diesem 
Array einen möglichst kleinen Hash basteln? Ich habe mich mit Hashs noch 
überhaupt nicht auseinandergesetzt und keine Ahnung ob das so machbar 
ist bzw welcher Algorithmus da infrage käme.

Oder ist der Ansatz die Verbindungen als Bitmuster in einem Array zu 
speichern von vorneherein schon suboptimal? Wie gesagt, ich bezeichne 
mich immernoch als C Anfänger und denke durchaus auch mal "von hinten 
durch die Brust ins Auge".

Freue mich daher über eure Meinungen.

Gruß
Holger

von dercr (Gast)


Lesenswert?

Vll. habe ich da was falsch verstanden, aber wenn du nur bei 31 
Leitungen alles Verbindungen untereinander speichern willst, wie kommt 
man da auf 128 Byte? Ich komm da auf 62.

Sind alle Kombinationen möglich? Wenn ja kannst du Uneindeutigkeiten 
(aka Kollisionen) nicht vermeiden, d.h. Kabel werden falsch erkannt.
Je nachdem wie kritisch das ist, ist die Länge des Hashs ein Kompromiss 
zwischen Zuverlässigkeit (Wenig Kollisionen) und Speicherbedarf.

von dercr (Gast)


Lesenswert?

Nachtrag zum Speicherbedarf der Matrix:
Wenn 1 mit 13 verbunden ist, ist 13 auch mit 1 verbunden, richtig? Das 
muss also nicht nochmal gesondert gespeichert werden.

von René H. (Gast)


Lesenswert?

Hmm... was willst Du mit einem Hash? Ein Hash lässt sich nicht 
zurückrechnen, dass ist ja nicht der Zweck eines Hash Wertes.

Wenn ich Dich richtig verstehe, willst Du die Daten komprimieren? Wenn 
ja, wäre evtl. Base64 etwas.

Grüsse,
René

von Holger K. (zaldo)


Lesenswert?

Ja das Stimmt natürlich, für die Temperaturkompensation brauche ich 
natürlich kein Feld im Array zu verplempern.

Es sind alle Kombinationen möglich - aber unwahrscheinlich. Kollisionen 
meißt nicht problematisch, er kann ja auch anzeigen, dass es zwei 
verschiedene Kabel sein könnten.

Doppelt speichere ich die Verbindungen ja auch nicht. Ich schicke meinen 
Prüfstrom auf Leitung 1, und schaue dann auf welchen Leitungen was 
ankommt (das Bitmuster welches ich abspeichere).

von Holger K. (zaldo)


Lesenswert?

René H. schrieb:
> Hmm... was willst Du mit einem Hash? Ein Hash lässt sich nicht
> zurückrechnen, dass ist ja nicht der Zweck eines Hash Wertes.

Brauche ich doch auch nicht. Ich speichere den Hash im EEProm und ordne 
einen Namen zu. Wenn ich ein neues Kabel teste erstelle ich den Hash und 
prüfe ob dieser im EEprom bereits gespeichert ist. So zumindest in 
meiner Vorstellung.

von René H. (Gast)


Lesenswert?

Naja, dann nimm irgend einen MD5 oder SHA Hash.

Grüsse,
René

von jois3 (Gast)


Lesenswert?

Hi Holger,

ein möglichst kleiner Hash führt prinzipbedingt zu möglichen 
Fehlerkennungen (false positive). Grund: Nehmen wir an, Du errechnest 
einen Hash mit 1 Bit, z.B. analog zum Parity Bit - dann hast Du einen 
möglichst kleinen "Hash". Die Aussagekraft ist allerdings auch klein. 
Also die Länge des Hash abhängig machen von der Anzahl der 
Kombinationen, die unterschieden werden sollen.

Btw, Hash würde Dir sagen, ob die Kombi genau passt. Die Nähe zu 
passenden Kombinationen liefert ein Gesamt-Hash normalerweise nicht - 
wenn also ein Kontakt zusätzlich besteht, der in der Referenz nicht 
verzeichnet ist, hast Du keinen Match.

Wenn trotzdem Hash, dann eventuell statt einem Gesamt-Hash z.B. vier 
kleinere; wenn drei passen, dann wird das Kabel zumindest vorgeschlagen. 
Aber möglicherweise sind Suchmaschinenansätze (in klein) besser 
geeignet.
Abhängig davon ergibt sich leider auch der Speicherbedarf.
Eventuell helfen hier sparse matrix-Ansätze 
(https://de.wikipedia.org/wiki/D%C3%BCnnbesetzte_Matrix).

Gruß, jois3

von StefG (Gast)


Lesenswert?

Hallo

So wie ich das sehe sind in den Arrays meist Nullen.
Man könnte das verlustfrei komprimieren (schwach besetzter Vektor)
indem man erst alle Array Elemente als Null annimmt.
Dann eine Liste erzeugen:
Element 2, 5, 10, 30 sind nicht Null.
Entsprechend kann der Original Array mit den Daten rekonstruiert werden.

Vielleicht hilft diese Methode, den Speicherplatz zu reduzieren...

von Nop (Gast)


Lesenswert?

Man kann auch CRC32 als Hash mißbrauchen - muß man halt mit dem 
Geburtstagsparadoxon ausrechnen, wie wahrscheinlich man Kollisionen hat. 
Bis zu IIRC etwa 10.000 Elementen ist das vernachlässigbar.

von c-hater (Gast)


Lesenswert?

Holger K. schrieb:

> Für ein 128 Byte Array (Plus
> Beschreibungstext) ist aber das 1024 Byte EEprom recht eng und damit zu
> der Stelle wo ich nach eurer Meinung fragen möchte: Könnte aus diesem
> Array einen möglichst kleinen Hash basteln?

Natürlich. Die Frage ist doch bloß: welche Wahrscheinlichkeit für eine 
Fehlerkennung (AKA: "Kollision") bist du bereit zu akzeptieren? Erst 
wenn du das quantifiziert hast, kann man dir eine Empfehlung für einen 
"möglichst kleinen" Hash geben.

Das ist doch sowas von klar, dass du dich schämen solltest, diese 
wichtige Kenngröße nicht gleich im OP angegeben zu haben...

von nicht"Gast" (Gast)


Lesenswert?

Um mal in eine andere Richtung zu lenken. Was ist mit einem größerem 
Eeprom? Die sind seriell (i2c oder spi) angebunden und bieten deutlich 
mehr an Speicher.

von Gerd E. (robberknight)


Lesenswert?

oder besser gleich Flash statt EEPROM. SPI-Flash in SO-8 gibt für ein 
paar Cent. Verfügbar bis in den Megabytebereich, das sollte erst mal 
reichen für so eine Tabelle.

von Zaldo (Gast)


Lesenswert?

Danke erstmal für eure Anregungen. Externer Speicher wäre natürlich eine 
Möglichkeit, allerdings habe ich nurnoch PA3, PA6 und PA7 frei, SCL SDA, 
MOSI, MISO.... Alle schon belegt. Voraussetzung wäre also das man in der 
Library die Pins "umbiegen" kann. Allerdings ist ein externes EEPROM / 
Flash auf meiner gegenwärtigen Platine nicht vorgesehen. Gut, könnte man 
jetzt mit einem Tropfen Kleber und etwas jumper-wire dranbasteln. Aber 
soviel Aufwand wollte ich garnicht betreiben. Es war im wesentlichen 
eine Idee für ein kleines Zusatzfeature, ein nice-to-have. Und wenn ich 
30 Kabelsignaturen nebst einer maximal 15-Stelligen Beschreibung da 
unterbringe reicht mir das schon dicke. Mehr ist natürlich immer 
schoner, aber die gebräuchlichsten Kabel benennen zu können würde mir 
schon genügen. Wenn es garnicht ginge wäre auch nicht schlimm, in meiner 
ursprünglichen Idee kam das ja garnicht vor. Fände es nur etwas 
komfortabler.

Das der Hash, je kleiner er ist auch umso weniger eindeutig wird ist 
sogar mir klar. Leider fehlt mir die Vorstellung einzuschätzen, wieviele 
Kollisionen ich bei einem 128 Bit MD5 Hash zu erwarten habe. Wenn er mir 
sagt, es könnte ein 3poliges XLR Kabel oder ein 16poliges Lastkabel sein 
wäre das nicht tragisch. Dumm wäre, wenn er ein Symmetrisches XLR Kabel 
nicht von einem unsymmetrischen unterscheiden könnte. Kriegsentscheidend 
wäre es indes nicht, denn beim erweiterten Test könnte man sich ja die 
tatsächliche Belegung auf dem Display anzeigen lassen. Wie gesagt, es 
ist nur ein nice2have.

Zum Punkt ein Gesamthash vs. vier kleine. Ist eigentlich nicht 
erforderlich. Wenn ich ein HDMI Kabel dranstecke, und er es nicht als 
HDMI Kabel erkennt, dann genügt mir das eigentlich schon um zu wissen 
das es hinüber ist. Warum genau es hinüber ist kann ich mir dann ja wie 
vorstehend beschrieben beim erweiterten Test anzeigen lassen. Bei 
manchen Kabeln macht das Sinn, wenn man sie reparieren kann/will. das 
HDMI Kabel käme in die Tonne, von daher brauche ich auch nicht zu wissen 
welche Leitung unterbrochen ist.

Sparse Matrix / Schwach besetzter Vektor: Klingt interessant, da muss 
ich mich mal mit einem ausgeruhten Kopf mit befassen.

Gruß
Holger

von Nop (Gast)


Lesenswert?

Zaldo schrieb:

> Und wenn ich
> 30 Kabelsignaturen nebst einer maximal 15-Stelligen Beschreibung da
> unterbringe reicht mir das schon dicke.

Bei 30 Kabeln langt eine CRC32 völlig aus. Das sind 4 Byte, plus die 15 
aus der Beschreibung, wären 19. Insgesamt mit 570 Bytes machbar.

Bei den geringen Größen muß man die CRC-Einträge nichtmal sortieren, 
sondern kann einfach durchloopen, ob der Eintrag in der (unsortierten) 
Liste ist oder nicht.

Codebeispiel für CRC32, und bei den wenigen Daten kann man das noch 
bitweise machen, also ohne Lookup-Tabelle:
http://create.stephan-brumme.com/crc32/#bitwise

> Leider fehlt mir die Vorstellung einzuschätzen, wieviele
> Kollisionen ich bei einem 128 Bit MD5 Hash zu erwarten habe.

Geburtstagsparadoxon ist hier das Stichwort, siehe Google. Ersetze dabei 
die Anzahl der Teilnehmer durch die Anzahl Deiner verschiedenen 
Kabelsorten, die Du erkennen willst, und die 365 aus dem Jahr durch 2^N, 
wobei N die Größe Deines Hash in Bit ist. Also 32 für CRC32.

Bei 30 Kabeln vernachlässigbar, bei etwa 10.000 Kabeln in der 
Größenordnung von etwa 1% Kollisionswahrscheinlichkeit.

von fop (Gast)


Lesenswert?

Hi,
die Frage ist auch, was kannst Du mit den Ergebnissen eines 
Hash-Vergleichs anfangen. Du kannst nur sagen, dies ist vermutlich ein 
intaktes Nullmodemkabel. Bei einem defekten Kabel, müsstest Du Dir eine 
Tabelle von Möglichkeiten schaffen, von denen man mit Einfach- oder 
Doppelfehlern auf den von Dir gemessenen Zustand kommt und deren Hashes 
mit den gespeicherten abgleichen. Klingt nicht prickelnd.
Dann lieber eine SD-Karte einbinden und so die Möglichkeit haben, per PC 
neue Kabel nachzupflegen.
Du kannst die Daten natürlich packen. Wobei Base64 das falsche Stichwort 
ist. Da werden Daten eher aufgeblasen, um sie für eine Übertragungsform 
bereit zu machen.
Ist natürlich eine Frage der Anzahl der möglichen Kabel. Was braucht 
mehr Platz der Code des Entpackers oder Mehrverbrauch durch die 
ungepackten Daten.

von Zaldo (Gast)


Lesenswert?

Das ist vom Ansatz her falsch gedacht. Wenn ich weiß dass ich ein 
Nullmodelkabel zum Testen angeschlossen habe, es aber als Nullmodemkabel 
nicht erkannt wird, dann brauche ich keine Tabelle die mir alle 
erdenklichen Fehler aufschlüsselt, denn ich weiß das es defekt ist. Je 
nach Kabel genügt das schon um es in die Tonne zu befördern, oder sich 
die tatsächlich ermittelte Belegung anzeigen zu lassen um den Fehler zu 
lokalisieren und das Kabel zu reparieren.

von fop (Gast)


Lesenswert?

Wenn die Stecker vergossen sind und die Dinger eh' in die Tonne wandern, 
wenn was nicht stimmt gebe ich Dir recht.
Wenn ich zum Kabelflicken schon so ein Gerät mit allem Komfort und 
-zurück nutze, möchte ich aber gerade nicht die Soll-Kabel-Belegung noch 
selber im Kopf haben oder gar raus suchen müssen, sondern mag konkrete 
Fehlermeldungen, wie Verbindung Pin 2 Stecker A zu Pin 3 Stecker B fehlt 
 ist zuviel  wackelt.

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

René H. schrieb:
> Hmm... was willst Du mit einem Hash? Ein Hash lässt sich nicht
> zurückrechnen, dass ist ja nicht der Zweck eines Hash Wertes.
>
> Wenn ich Dich richtig verstehe, willst Du die Daten komprimieren? Wenn
> ja, wäre evtl. Base64 etwas.
>
> Grüsse,
> René

Base64 komprimiert nicht, im Gegenteil, es bläht auf ...
Sinn von Base64 ist, rein binäre Werte in texbasierten Umgebungen 
transportieren zu können und z.B. eine Fehlinterpretation als 
Steuerzeichen zu vermeiden.

von Zaldo (Gast)


Lesenswert?

Was wackelige Pins angeht gebe ich Dir recht, der rest ist eine Frage 
des Anforderungsprofils. Wenn Du in der Regel kaputte Kabel hast und 
sollst/willst die Fehler suchen hast Du sicher recht. Hier geht es aber 
darum, dass die Kabel in aller Regel OK sind, und nur gelegentliche 
defekte aufgespürt/aussortiert/repariert werden, und da würde sich der 
Mehraufwand nicht lohnen.

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Holger K. schrieb:

> Nun kam mir in den Sinn, es wäre ganz schön wenn ich im EEprom
> Kabeltypen ablegen könnte, und der Tester könnte mir vorschlagen,
> welches Kabel er erkannt hat. Für ein 128 Byte Array (Plus
> Beschreibungstext) ist aber das 1024 Byte EEprom recht eng und damit zu
> der Stelle wo ich nach eurer Meinung fragen möchte: Könnte aus diesem
> Array einen möglichst kleinen Hash basteln? Ich habe mich mit Hashs noch
> überhaupt nicht auseinandergesetzt und keine Ahnung ob das so machbar
> ist bzw welcher Algorithmus da infrage käme.


Wenn jede Bitkombination möglich ist, ist ein Hash mit weniger Bit nicht 
mehr eindeutig.

von Zaldo (Gast)


Lesenswert?

Haben wir schon diskutiert, 100%ige Eindeutigkeit ist auch nicht 
erforderlich.

von Wolfgang (Gast)


Lesenswert?

Zaldo schrieb:
> Danke erstmal für eure Anregungen. Externer Speicher wäre natürlich eine
> Möglichkeit, allerdings habe ich nurnoch PA3, PA6 und PA7 frei, SCL SDA,
> MOSI, MISO.... Alle schon belegt.

Und was wäre dann das Problem bei Anbindung eines seriellen EEPROMs?
I2C ist ein Bus, wo durchaus mehr als ein Baustein dran hängen darf und 
über die I2C-Adresse selektiv zugegriffen werden kann. Bei SPI lassen 
sich ebenfalls mehrere Teilnehmer auf die Leitung setzen, von denen dann 
jeweils einer über Chip-Select für den Zugriff aktiviert wird.

von PittyJ (Gast)


Lesenswert?

Wolfgang schrieb:
> Zaldo schrieb:
>> Danke erstmal für eure Anregungen. Externer Speicher wäre natürlich eine
>> Möglichkeit, allerdings habe ich nurnoch PA3, PA6 und PA7 frei, SCL SDA,
>> MOSI, MISO.... Alle schon belegt.
>
> Und was wäre dann das Problem bei Anbindung eines seriellen EEPROMs?
> I2C ist ein Bus, wo durchaus mehr als ein Baustein dran hängen darf und
> über die I2C-Adresse selektiv zugegriffen werden kann. Bei SPI lassen
> sich ebenfalls mehrere Teilnehmer auf die Leitung setzen, von denen dann
> jeweils einer über Chip-Select für den Zugriff aktiviert wird.

Und mit 3 freien Ports könnte man notfalls I2C über Bitbang betreiben.
Einfacher ist es aber einen Port als SPI Slave-Select zu betreiben.

von Zaldo (Gast)


Lesenswert?

Okay, ich habe mich da vielleicht unglücklich ausgedrückt, mit "Bereits 
belegt" meinte ich nicht, dass da schon irgendetwas anderes dranhängt 
das I2C oder SPI spricht, sondern dass die Pins bereits als I/Os genutzt 
werden. Wie ich aber schon gesagt habe steht das nicht zur Debatte, da 
es auf meiner Platine nicht vorgesehen ist, und es sich bei dieser 
Funktion auch nur um ein Gimmick handelt, das zu realisieren mit 
Bordmitteln und ohne zusätzlichen Aufwand sein soll. Wenn ich bereits 
während dem Schaltungsdesign diese Idee gehabt hätte, hätte ich es 
vielleicht berücksichtigt, aber nur deswegen jetzt eine neue Platine zu 
erstellen ist mir diese Funktion (die in dieser Tiefe eh nicht benötigt 
wird) nicht wert.

von S. R. (svenska)


Lesenswert?

Dann implementiere I2C oder SPI halt mit Bitbanging (also mit normalen 
GPIOs), das geht auch. Du brauchst ja keinen massiven Datendurchsatz...

von fop (Gast)


Lesenswert?

Was mir noch so einfällt : spare doch einfach den Platz für den 
Kabelnamen. Gibt einfach eine Zahl aus, die den Index unter dem der Hash 
abliegt angibt. Ein Aufkleber auf dem Gehäuse gibt dem Benutzer dann 
Auskunft über die Zuordnung. Wenn meist viele gleiche Kabel auf einmal 
getestet werden, auch nicht so schlimm, weil man dann nur einmal schaut, 
welche Zahl angezeigt werden müsste.

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.