Heb een "long number" en die wil ik vullen met een een Array. Probleem

Heb een werkende fisher-yates shuffled en een bubble unsort die keurig voor mij de getallen 0,1,2,3,4,5,6,7,8,9 mixen in een Array.

Probleem is bij een 74HCT595 (10 chips) SPI 10 led-segmenten module dat ik daar gebruik maak van long number omdat het getal bv 1234567890 gewoonweg te lang is anders.

Aansturen van de SPI gaat perfect en kan achter de long zetten wat ik wil en die verschijnen keurig in een rij.
Pobleem is dus dat ik de gemixte getallen 0 t/m 9 in een Array heb en ik krijg het niet voor elkaar om achter long een array te zetten.

Of ik kijk overal overheen of ik wil iets wat niet kan (volgens mij kan alles op een draaideur achter je dichtgooien na).

Anderzijds kan een andere oplossing met fisher of bubble die ik nu heb ook goed zijn. Als ik maar een waarde achter long kan plaatsen. Bijvoorbeeld long = {ongesorteerd};

union gebruiken:

union {
   long number;
   char numberArray[4];
} x;

x.number is de benadering als long
x.numberArray is de benadeding van het geheugen als array.
Houd wel rekening met de endianness van een long. De Arduino gebruikt little Endian (zi : Endianness - Wikipedia)

Zal eens met de union functie aan de slag gaan vanmiddag. Ongetwijfeld zal ik tegen de Endianess aanlopen en weet dan in ieder geval van het bestaan af. Dank daarvoor.

dan maak je toch 10 bytes aan in een string want die kun je wel versturen, waarom moet die long ernaartoe.

Ik zit nog eens te lezen wat hij nu precies wil :slight_smile: Nou ja we horen het wel :slight_smile:

Nou de code komt van 2 verschillende websites. Die 2 moeten in elkaar verweven worden.

De eerste zorgt netjes voor de getallen 01234567890, zoals in long number is gedefinieerd.

//Pin connected to latch pin (ST_CP) of 74HC595
const int latchPin = 8;

//Pin connected to clock pin (SH_CP) of 74HC595
const int clockPin = 12;

//Pin connected to Data in (DS) of 74HC595
const int dataPin = 11;

//7SegLED number of Segments
const int ledArray = 16;
 
byte byteData[ledArray] = {0};
char strData[ledArray] = {0};

//ledArray
//-9999999 to 99999999
long number = 01234567890
 
void setup() {
  //Arduino pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
  
}
 
void loop() {
 sprintf(strData, "%ld", number);
 //char byte
 setDataFormat(strData, byteData);
  
 digitalWrite(latchPin, LOW);
 for(int i=ledArray-1; i>=0; i--){
     shiftOut(dataPin, clockPin, MSBFIRST, byteData[i]);
 }
 digitalWrite(latchPin, HIGH);
  
}
 
void setDataFormat(char* strData,byte *byteData){
  int numofNull=0;
  // char byte
  for(int i=0; i<ledArray; i++){
    switch(strData[i]){
      case '\0':
        byteData[i]=0xff;
        numofNull++;
        break;
      case '0': 
        byteData[i]=0xc0;
        break;
      case '1':
        byteData[i]=0xf9;
        break;
      case '2':
        byteData[i]=0xa4;
        break;
      case '3':
        byteData[i]=0xb0;
        break;
      case '4':
        byteData[i]=0x99;
        break;
      case '5':
        byteData[i]=0x92;
        break;
      case '6':
        byteData[i]=0x82;
        break;
      case '7':
        byteData[i]=0xf8;
        break;
      case '8':
        byteData[i]=0x80;
        break;
      case '9':
        byteData[i]=0x90;
        break;
      case '-':
        byteData[i]=0xbf;
        break;
    }
  }
  // char byte

  for(int i=0; i<numofNull; i++){
    byte tmp[ledArray];
    int j;
    for(int i =0; i<ledArray; i++){
      tmp[i]=byteData[i];
    }
    for(int i =0; i<ledArray; i++){
      if(i==0){
        j = ledArray-1;
      }else{
        j = i-1;
      }
      byteData[i] = tmp[j];
    }
  }
}

Nummer 2 is een random waarbij het mij niet uitmaakt of het Bubble of Fisher is. Doel is dat 0123456789 steeds gemixed worden en die long number na een druk op een knop steeds veranderd.

Druk op de knop zet ik er nog wel in, dat is niet zo moeilijk. Mag nu in een loop zelfs met een pauze

// Arduino comparative shuffle test
// Fisher-yates vs "bubble unsort"
// 2010.03.13 raron


int anArray[] = {0,1,2,3,4,5,6,7,8,9};
int elements = sizeof(anArray) / sizeof(int);


void setup()
{
 Serial.begin(9600);
 delay(2000);
 int noise = analogRead(2);
 randomSeed(noise);


 // Fisher-yates
 shuffle(anArray, elements, sizeof(int));
 Serial.println("---- fisher-yates shuffled ---- ");
 printArray(anArray, elements);

}


void loop()
{
}




void printArray(int *array, int elem)
{
   for (int p=0; p<elem; p++)
   {
     Serial.print("array[ ");
     Serial.print(p);      Serial.print(" ] = ");
     Serial.println(array[p]);
   }
}

// shuffle an array using fisher-yates method, O(n)
void shuffle(int *array, int nmemb, int size)
{
   int r;
   
   while (nmemb > 1) {                                                                      
       r = rand_range(nmemb--);                                                              
       shuffle_swap(nmemb, r, array, size);
   }
}

//----End Code---

De random is dus een array die ik op de plaats van long number wil hebben. Een getal mag niet dubbel in de rij voorkomen.

In C# op de PC werkt alles zoals ik wil en die taal snap ik ook met grafische weergave op het scherm.

Nu op Arduino met de DFRobot 8 LED-Segment SPI gebaseerd op de shift 75HCT595 wil me maar niet lukken.

Dit is een onderdeel van een geheel project, waarvan de rest wel werkt.

Alle ideeën welkom en tips en advies ook.

Dus begrijp ik je goed dat je eigenlijk die array omgezet wilt hebben in een long?
Dan kan je toch gewoon een loop langs die array laten lopen?

uint32_t number = 0;
for (uint8_t i = 0; i < 10; i++) {
   number = (number * 10) + array[i];
}

Ah ja, de int32 heb ik totaal over het hoofd gezien.

Met de union gaat het niet lukken. Waarschijnlijk is de 0 aan het begin een probleem en wordt niet als zodanig gezien

Tot in de vroege uurtjes bezig geweest en kom er niet aan uit. Ga maar eerst eens een beschrijving maken om duidelijkheid voor de lezers hier te verschaffen.

Staat er wel, maar imo wat onduidelijk.

Nou ben een stap verder. Het is inmiddels 1 Sketch zomder fouten erin.

Op 1 ding echter na. Het lukt mij dus gewoonweg niet om in de variabele number de random gegenereerde getallen te krijgen. Steeds het laatste getal, maar hij vult geen array.
Op de seriële monitor keurig wat ik dus in number wil hebben.

Ik heb hem nu even gelaten zoals hij iig de display 01234567890 aangeeft en in de seriële monitor keurig de getallen gemixt (Let op ik gebruik 2 random generators ivm een checksum die ik later nodig heb als ik aan de input ga werken.

int array[10] = {0,1,2,3,4,5,6,7,8,9} ;
//Pin latch pin (ST_CP) 74HC595
const int latchPin = 8;
//Pin clock pin (SH_CP) 74HC595
const int clockPin = 12;
//Pin  Data  (DS)74HC595
const int dataPin = 11;
//7SegLED
const int ledArray = 16;
 
byte byteData[ledArray] = {0};
char strData[ledArray] = {0};

long number = 1234567890;
 
void setup()

{
    Serial.begin(9600);
 delay(2000);
 int noise = analogRead(2);
 randomSeed(noise);

 for (int i= 0; i< 10; i++) 
 {
   int pos = random(10);
   int t = array[i];   
   array[i] = array[pos];
   array[pos] = t;
 }

 for (int i= 0; i< 10; i++)
 {
  Serial.print(array[i]);
  // number = (array[i]);
  randomSeed(noise);
 }
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
}
}
void loop() {

 sprintf(strData, "%ld", number);
 //char byte
 setDataFormat(strData, byteData);
  
 digitalWrite(latchPin, LOW);
 for(int i=ledArray-1; i>=0; i--){
     shiftOut(dataPin, clockPin, MSBFIRST, byteData[i]);
 }
 digitalWrite(latchPin, HIGH);
  
}
 
void setDataFormat(char* strData,byte *byteData){
  int numofNull=0;
  for(int i=0; i<ledArray; i++){
    switch(strData[i]){
      case '\0':
        byteData[i]=0xff;
        numofNull++;
        break;
      case '0': 
        byteData[i]=0xc0;
        break;
      case '1':
        byteData[i]=0xf9;
        break;
      case '2':
        byteData[i]=0xa4;
        break;
      case '3':
        byteData[i]=0xb0;
        break;
      case '4':
        byteData[i]=0x99;
        break;
      case '5':
        byteData[i]=0x92;
        break;
      case '6':
        byteData[i]=0x82;
        break;
      case '7':
        byteData[i]=0xf8;
        break;
      case '8':
        byteData[i]=0x80;
        break;
      case '9':
        byteData[i]=0x90;
        break;
      case '-':
        byteData[i]=0xbf;
        break;
    }
  }

  for(int i=0; i<numofNull; i++){
    byte tmp[ledArray];
    int j;
    for(int i =0; i<ledArray; i++){
      tmp[i]=byteData[i];
    }
    for(int i =0; i<ledArray; i++){
      if(i==0){
        j = ledArray-1;
      }else{
        j = i-1;
      }
      byteData[i] = tmp[j];
    }
  }
}
number = number + (array[i] * 10^(10-i));

zoiets?

Een alternatief (eenvoudiger) is als volgt:

number = number * 10;         // vermenig number 10 zodat de digit een naar links schuit
number = number + array[i]; // tel de waar uit de array erbij op

Ik heb in de seriele monitor even de output gezet wat er op de SPI Display gebeurd.

4 1234567924
2 1234567953
0 1234567961
5 1234568014
1 1234568026
3 1234568053
6 1234568109
9 1234568198
7 1234568266
8 1234568347

De onderste reeks 1234568347 heb ik bij het gegenereerde random 4205136978 gekregen.

Het stukje code van mijn gewaardeerde voorganger Nico Verduin heb ik hier gezet met een extra serial.print erin

for (int i= 0; i< 10; i++)
 {
  Serial.print(array[i]);
  Serial.print(" ");
  number = number + (array[i] * 10^(10-i));
  Serial.println (number);

Neem ik de eenvoudige code dan krijg ik een negatief getal in de display met herhalingen erin.

Dat je een negatief getal krijgt komt vermoedelijk omdat je een long gebruikt. Je moet er unsigned long of uint32_t (=beter) van maken.

Foutje van mij :). De cijfers zijn de ascii waardes in de tabel. Die beginnen bij hex '30' voor de 0 en lopen zo op. Je moet er dus 0x30 vanaf trekken. Bijgaand stukje testcode laat zien dat het zo goed werkt:

char array[11] = "4205136978";
uint32_t number;

//The setup function is called once at startup of the sketch
void setup()
{
    Serial.begin(9600);
    //
    // test 1 moeilijke formule
    //
    number = 0;
    Serial.println(array);
    for (uint8_t i = 0; i < 10; i++) {
        number = number * 10;
        number = number + (array[i] - 0x30);
        Serial.println(number);
    }
}

// The loop function is called in an endless loop
void loop()
{
//Add your repeated code here
}

En de uitkomsten:

4205136978
4
42
420
4205
42051
420513
4205136
42051369
420513697
4205136978

De eerste regel is als string daarna het inschuiven in number.

Hallo Nico,

Ik krijg je stukje code niet correct in mijn Sketch.

  1. Doel is om de getallen 0,1,2,3,4,5,6,7,8,9 te shuffelen via Fisher Yates of Bubble Unsort (Dat lukt prima)
  2. De SPI interface (LED Segment, wil graag een geheel getal aangestuurd krijgen)

Wat ik nu heb is code die er perfect uitziet en alles werkt los als zodanig.

Voeg ik het eea samen dan krijg ik met geen mogelijkheid de getallen ongesorteerd, zonder dubbele op de SPI

Kan het wiel opnieuw gaan uitvinden, echter ik zie werkende Voltmeters, Counters, Frequentiemeters etc.

De functie char array[11] = "4205136978"; wordt niet geaccepteerd omdat het een string is.
De Serial.println(number); zou daarintegen de oplossing zijn als ik de laatste als long kan definiëren.

Eigenlijk aan het einde van je gegeven sketch iets van
Long (ongesorteerd) = number

Gebruik 2 unsort werkwijze en een random noise wat perfect werkt. Het stukje code wat ik nog niet geplaatst heb ivm communicatie-doeleinden mag 1 van de 2 unsort methoden zijn.

Vraag is eigenlijk dan ook. Ongetwijfeld zie je waar ik wat moet zetten. Voor mij is het een beetje abacadabra aan het worden, alleer ik er enorm veel van. Kom uit de C# hoek en gebruik volledig andere coding. Daar werkt het perfect. De SPI nekt me uiteindelijk.

Nou ken ik toevallig de C# hoek ook, maar zo verschillend is dat niet. Je had dit zelfs kunnen ontwikkelen binnen C# als unmanaged code.

Maar voor jouw :):

// Do not remove the include below
#include "testi2c.h"

char array1[11] = "4205136978";
int array[10];
uint32_t number;

//The setup function is called once at startup of the sketch
void setup()
{
    Serial.begin(9600);
    //
    // ff die chars omzetten naar ints
    //
    for (uint8_t i = 0; i < 10; i++){
        //
        // ff van de cahr een int maken door er 0x30 af te trekken. het zijn immers
        // cijfers
        //
        array[i] = array1[i] - 0x30;
    }
    //
    // meest eenvoudige manier. Hier kan je natuurlijk ook een functie van maken
    //
    number = 0;                            // nummer op 0 zetten
    Serial.println(array1);                // ff de reeks als string tonen
    for (uint8_t i = 0; i < 10; i++) {    
        number = number * 10;            // cijfers naar links schuiven
        number = number + array[i];        // nieuwe getal toevoegen    
        Serial.println(number);            // en tussen resultaat printen
    }
}

// The loop function is called in an endless loop
void loop()
{
//Add your repeated code here
}

Je kan van dat specifieke code ook een functie maken en geef je "number" terug. Wat je verder allemaal doet met sorteren enz is in dit topic niet van toepassing. Immers daar vroeg je niet om. In bovenstaande code zet ik ff die string om in een int array wat identiek is aan jouw code.

De Array voor de SPI 8 Segment in de variabele number kan ik vrij goed krijgen.
Het werkt bijna.

Problemen zijn 2 dingen.
A: Gaat bij de laatste shift de mist nogal eens in (als de int I 10 is)
B: Als de random Array begint met een 0

Heb er al een delay in gezet van 50 wat al minder "A" fouten gaf.

/*
 Name:    TestRandSPI.ino
 Created: 12/28/2015 01:31:20 AM
*/
uint32_t number= 0;
int array[10] = {0,1,2,3,4,5,6,7,8,9} ;

void setup()
{
 Serial.begin(9600);
 delay(2000);
 
 int noise = analogRead(2);
 
 randomSeed(noise);
 
 for (int i= 0; i< 10; i++) 
 {
   int pos = random(10);
   int t = array[i];   
   array[i] = array[pos];
   array[pos] = t;
 }

 for (int i= 0; i< 10; i++)
 {
   Serial.print(i);
   Serial.print(": ");
   Serial.print(array[i]);
   Serial.println("");
 }

    for (int i = 0; i < 10; i++) {    
        number = number * 10;            // cijfers naar links schuiven
        number = number + array[i];        // nieuwe getal toevoegen    
        Serial.println(number);            // en tussen resultaat printen
        delay(50);
    }
 
}
void loop(){

}

Bij een nieuw getal toevoegen gaat ie veelal de mist in met number=number+array*;*
een Serial.println(array*); laat wel zien dat de waarde juist is,*
echter met het toevoegen ontstaat fout A.
Voorbeeld:
9
9
0
90
5
905
6
9056
7
90567
4
905674
1
9056741
8
90567418
3
905674183
2
466807240 // Vreemde eend in de bijt op de Seriële monitor te zien.

De fout A is eruit.
De int array[11] = {0,1,2,3,4,5,6,7,8,9} ; moet [11] zijn ipv 10.
De fout met het starten van een 0 in de verkregen Array zit er nog in.

/*
 Name:    TestRandSPI.ino
 Created: 12/28/2015 03:51:20 AM
*/
uint32_t number= 0;
int array[11] = {0,1,2,3,4,5,6,7,8,9} ;

void setup()
{
 Serial.begin(9600);
 delay(2000);
 
 int noise = analogRead(2);
 
 randomSeed(noise);
 
 for (int i= 0; i< 10; i++) 
 {
   int pos = random(10);
   int t = array[i];   
   array[i] = array[pos];
   array[pos] = t;
 }

 for (int i= 0; i< 10; i++)
 {
   Serial.print(i);
   Serial.print(": ");
   Serial.print(array[i]);
   Serial.println("");
 }

    for (int i = 0; i < 10; i++) {    
        number = number * 10;            // cijfers naar links schuiven
        number = number + array[i];        // nieuwe getal toevoegen    
        Serial.println(number);            // en tussen resultaat printen
        delay(50);
    }
 
}
void loop(){

}

Een unsigned long kan nooit meer zijn dan 2^32. Dus als jij een 5 of hoger in dat eerste cijfer wil stoppen ga je de mist in
En heb je als eens die random getallen bekeken? Mogelijk is er een fout in de random functie. een waarde 10 zou niet mogen. Wat niet wil zeggen dat dat niet gebeurt.
array[11] is onjuist. index=10 mag niet voorkomen