ublo
bogdan's (micro)blog

bogdan » how to build a maze

01:42 pm on Oct 7, 2018 | #more | tags:

in this post i'll use C to construct a maze, that will be later used for my swarm experiments.

i'll be using a graph-model for the maze: each vertex is a room from the maze, which is connected by edges to other rooms. in a 2-D classic maze of size m×n, with m spanning from top to bottom and n spanning from left to right, each room has at most 4 neighbors. this means each vertex in my graph will have at most 4 edges: top, bottom, left and right. the total number of edges is m×(n-1) for vertical edges (top, bottom) and (m-1)×n for horizontal edges (left, right). in order to create a maze, in the previously described graph, i'll choose using a version of Dijkstra algorithm a maximum spanning tree. to make the maze random, i'll mark each edge with a random weight and then run the maximum spanning tree algorithm.

maze model

i'll be using matrices as data structures. this means that each vertex will be labeled with a pair (i,j) with i from 0 to m-1 and j from 0 to n-1. as the graph is not oriented, i'll have:

  • if (i,j) is linked to (i,j+1), than i'll store in my matrix, on position (i,j) the weight of the edge [(i,j),(i,j+1)];
  • if (i,j) is linked to (i+1,j), than i'll store in my matrix, on position (i,j+n) the weight of the edge [(i,j),(i+1,j)];
  • no need to store the [(i,j),(i,j-1)] edge as it's equivalent to [(i,(j-1)),(i,(j-1)+1)];
  • also, no need to store connections at the lower and right edge of the maze;

maze storage

the number of required edges' weights can be held in a m×(2×n-1)-n vector, corresponding to an incomplete m×(2×n-1) matrix.

building the weight matrix

this step is quite easy. just loop over all m×(2×n-1)-n and assign them a random value between 1 and 255. i'll be using 0 to represent edges that are missing.

/**
 * the function initializes the weights matrix as described above;
 * @param m (int) the dimension of the maze on top-bottom axis;
 * @param n (int) the dimension of the maze on left-right axis;
 * @returns: an uint8_t matrix, of size (m-1)*2*(n-1) filled with random data;
 */
uint8_t * maze_weight_init (int m, int n) {
        /** @var maze the weight matrix */
        uint8_t * maze;
        /** @var c is  a variable index */
        int c;

        /** i reserve the space in the computer memory for the matrix */
        maze = (uint8_t *) malloc ((m * (2 * n - 1) - n) * sizeof (uint8_t));
        /** if memory reservation is successful, i'm filling the matrix */
        if (maze != NULL)
                for (c = 0; c < m * (2 * n - 1) - n; c++)
                        *(maze + c) = (uint8_t) ((1 + rand ()) % 256);

        return maze;
}

tip:
the matrix is stored as a single vector, meaning a cell on the position (i,j) can be accessed by finding as the (i×cols+j)-th component of the vector. this map is bijective, meaning that the i-th component of the vector corresponds to position (i/cols, i%cols) in the matrix, where / is the integer division and % is the reminder operator.

sorting the weight matrix

the matrix is not useful like this. it needs to be sorted. i'm using a simple (inefficient) bubble sort algorithm. i'll take advantage of how i stored the matrix so i can simply arrange the associated vector. i'll create a vector into which i'll keep the association of indices.

bubble sort works like this: take the first weight from the vector, and if it's heavier that the one above, swap their places. this has to be repeated until the entire vector is sorted: this happens when there are no swaps on a swipe.

/** the function is sorting the associated vector V, returning a mapping of the
 * sorted indices, M, with V(i) being the original vector, while V(M(i)) is the sorted one
 * @param weights (uint8_t *) is the original vector
 * @param m (int) is the top-bottom size of the maze
 * @param n (int) is the left-right size of the maze
 * @returns: an int mapping vector between the sorted version and the original one
 */
int * maze_edges_sort (uint8_t * weights, int m, int n) {
        /** @var indices the vector containing the sorted mapping */
        int * indices;
        /**
         * @var c a variable index
         * @var t a temporary variable used in swapping two indices
         * @var o a temporary variable storing last index swapped
         * @var l, initially the length of the weights vector,
         *        after, the length of the unsorted vector
         */
        int c, t, o, l = m * (2 * n - 1) - n;

        /** initialize indices with an identity mapping i->i */
        indices = (int *) malloc (l * sizeof (int *));
        for (c = 0; c < l; c++)
                *(indices + c) = c;

        if (indices != NULL)
                /** while there's still some unsorted part of the vector */
                while (l > 0) {
                        /** o holds the last swapped value */
                        o = 0;
                        /** i'm looping until the end of the unsorted vector */
                        for (c = 1; c < l; c++) {
                                /** if the weights don't respect the sort order, swap them */
                                if (*(weights + *(indices + c - 1)) > *(weights + *(indices + c))) {
                                        /**
                                         * of course, i'm swapping indices in the mapping,
                                         * not real values, as the initial vector remains
                                         * unchanged, only the mapping function deviates from
                                         * identity map
                                         */
                                        t = *(indices + c - 1);
                                        *(indices + c - 1) = *(indices + c);
                                        *(indices + c) = t;
                                        /** store the last swapped index */
                                        o = c;
                                }
                        }
                        /** the length of the unsorted vector equals the last swapped index */
                        l = o;
                }

        return indices;
}

building the maximum spanning tree

this algorithm is more complex that the previous ones. for easier understanding, i need to explain some notions:

  • a graph is a collection of vertices and edges, each edge connecting two vertices; it can and usually has loops - meaning starting from one vertex, it can be reached again going edge-by-edge; like a city with ring-roads;
  • a tree is a graph with no loops; it means that starting with a vertex, and going edge-by-edge you'll never get to the same vertex again; like a computer network;
  • in a graph (including a tree), a sub-tree is a collection of vertices and edges from the initial graph that behave like a tree - there are no loops;

i'll start with an empty set of sub-trees from the original graph. this will be called a forest set. forests have at least one tree. at the end of the algorithm i'll have in this set a tree that will link all vertices from the original graph. this is called a maximum spanning tree.

with each sorted edge, lighter to heavier, i'll do the following:

  • if the edge is not connected to any sub-tree from my sub-tree set, i'll add the edge to the sub-tree set, coloring it with a new color;
  • if the edge has one vertex connected to a sub-tree in my sub-tree set, i'll add the edge to the sub-tree set, coloring it with the same color as the rest of the sub-tree;
  • if the edge has vertices on different sub-trees, than i'll add the edge and color both sub-trees, as well as the edge, with a common color. i'll use indexed colors, so i'll choose the minimum color;
  • if the edge has vertices on the same sub-tree, i'll skip this edge; in this situation, the edge is creating a loop in the tree, making it a graph;
/**
 * the procedure takes as parameters a weight matrix together with its size
 * and modifies in place the weights matrix, removing the unnecessary edges
 * an edge is kept, if the weight is strict positive, while an edge is
 * deleted, if its weight is zero.
 * @param weights (uint8_t *) is the weight vector
 * @param m (int) is the maze top-bottom size
 * @param n (int) is the maze left-right size
 */
void maze_init (uint8_t * weights, int m, int n) {
        /**
         * @var indices is the sorted mapping for the weights vector;
         * @var matrix is a vector-stored matrix that has 0 on (i,j)
         *         0 on (i,j) position, if the (i,j) vertex was not visited
         *         color>0 on (i,j) position, if the (i,j) vertex was visited
         *         and (i,j) is part of the "color" sub-tree
         */
        int * indices, * matrix;
        /**
         * @var c,d are variable indices;
         * @var row,col are the row and column indices in the @see matrix
         * @var n_row,n_col are the indices for the vertex connected to
         *        (row,col);
         * @var min_color is the minimum "color" when merging an existing
         *        sub-tree with a new edge. the edge can link two existing
         *        sub-trees, meaning i'll have to choose a single color for both
         * @var max_color is analog with @see min_color;
         * @var color is the current available color for new sub-trees;
         */
        int c, d, row, col, n_row, n_col, min_color, max_color, color = 1;

        /** reserve memory for the is-visited? matrix */
        matrix = (int *) malloc (m * n * sizeof (int));
        for (c = 0; c < m * n; c++)
                *(matrix + c) = 0;

        /** sort the graph weights */
        indices = maze_edges_sort (weights, m, n);

        /** loop through sorted edges */
        for (c = 0; c < m * (2 * n - 1) - n; c++) {
                /** get the edge first vertex label as (row, col) */
                row = *(indices + c) / (2 * n - 1);
                col = *(indices + c) % (2 * n - 1);

                /**
                 * based on how is stored, get the label for the
                 * second vertex associated with the edge
                 */
                if (col < n - 1) {
                        n_row = row;
                        n_col = col + 1;
                }
                else {
                        col = col - n + 1;
                        n_row = row + 1;
                        n_col = col;
                }

                /**
                 * check if the current edge can be added to the forest:
                 * the edge needs to fulfill all requirements:
                 * - the edge is not already part of a tree, meaning that both
                 *        vertices are the same non-zero color
                 */
                if (
                        (*(matrix + row * n + col) == *(matrix + n_row * n + n_col)) &&
                        *(matrix + row * n + col) > 0
                ) {
                        *(weights + *(indices + c)) = 0;
                        continue;
                }

                /**
                 * find the color of the new vertices, by getting minimum and
                 * maximum color. both can be zero, if we start a new sub-tree
                 */
                if (*(matrix + row * n + col) < *(matrix + n_row * n + n_col)) {
                        min_color = *(matrix + row * n + col);
                        max_color = *(matrix + n_row * n + n_col);
                }
                else {
                        min_color = *(matrix + n_row * n + n_col);
                        max_color = *(matrix + row * n + col);
                }

                if (min_color == 0) {
                        /**
                         * here, min = max = 0, this means we have a new sub-tree
                         * so i color it with the next available color
                         */
                        if (max_color == 0) {
                                *(matrix + row * n + col) =
                                *(matrix + n_row * n + n_col) = color ++;
                        }
                        /** here, the edge has an open end, the other is connected */
                        else {
                                *(matrix + row * n + col) =
                                *(matrix + n_row * n + n_col) = max_color;
                        }
                }
                else {
                        /**
                         * here min, max > 0, both different, this means that the
                         * edge is connecting two different color sub-trees, so i
                         * make both the same color (min color)
                         */
                        *(matrix + row * n + col) =
                        *(matrix + n_row * n + n_col) = min_color;

                        for (d = 0; d < m * n; d++)
                                if (*(matrix + d) == max_color)
                                        *(matrix + d) = min_color;
                }
        }

        /** remember to free the reserved memory */
        free (indices);
        free (matrix);
}

putting it all together

piece of cake. first, i'll have to initialize my weights. than, to build the maximum spanning tree. a good exercise is to display the maze on the screen using ASCII art.

#include  /** required for malloc, srand and rand functions */
#include  /** useful for printing stuff, with printf */
#include  /** i need the uint8_t definition */
#include  /** i need the time function */

/**
 * this is the normal, unix-style format for the program entrypoint
 * @param argc (int) is the number of arguments from the command line;
 * @param argv (char **) is an array of strings, containing the command line arguments;
 * @returns: an integer, zero if no error has occurred.
 */
int main (int argc, char ** argv) {
        /** @var weights (uint8_t *) my weights matrix */
        uint8_t * weights;
        /** @var m, n (int) the maze size */
        int m = 4, n = 4;

        /** make the random numbers random ­čÖé */
        srand (time (NULL));

        /** initialize the weights matrix */
        weights = maze_weight_init (m, n);
        /** build a maximum spanning tree from the matrix */
        maze_init (weights, m, n);

        /** tell the operating system that there's no error */
        return 0;
}

bogdan » arduino: conectarea la octave

10:29 pm on Apr 9, 2018 | #more | tags:

├«n urma rug─âmin╚Ťii profesorului Stamatin, de c├ó╚Ťiva ani ╚Ťin un curs la Facultatea de Fizic─â din M─âgurele. dac─â ini╚Ťial numele ┬źmodelare ╚Öi simulare┬╗ ascundea ecua╚Ťii matematice ╚Öi metode numerice, recent am ├«nlocuit diferen╚Ťialele cu Arduino, ├«n ova╚Ťiile celor c├ótorva studen╚Ťi care frecventeaz─â cursul. dot─ârile limitate m-au f─âcut s─â devin creativ cu materialele de curs, iar rezultatul mi s-a p─ârut suficient de interesant pentru a-l reproduce aici. a╚Öa c─â:

GNU Octave:
GNU Octave este o alternativa gratuit─â a MathWorks MatLab. ambele fac ├«n mare acela╚Öi lucru pentru utilizatorul de r├ónd: efectueaz─â extrem de eficient opera╚Ťii matematice cu matrice. mai mult, ├«n cele mai multe cazuri, codul scris pentru unul func╚Ťioneaz─â f─âr─â probleme ├«n cel─âlalt. GNU Octave poate fi desc─ârcat de aici.

recomand varianta zip, pentru arhitectura potrivit─â calculatorului t─âu cu men╚Ťiunea c─â ├«n cazul ├«n care nu ╚Ötii ce ├«nseamn─â arhitectur─â, po╚Ťi alege cu ├«ncredere varianta care are ├«n numele fi╚Öierului w32. fi╚Öierul desc─ârcat este o arhiv─â de tip zip ╚Öi necesit─â dezarhivare. dac─â utilizezi Microsoft Windows 10, po╚Ťi folosi cu ├«ncredere utilitarul integrat ├«n Windows Explorer. vei ob╚Ťine un director care con╚Ťine octave.bat, fi╚Öierul pe care trebuie s─â dai dublu-clic pentru a porni aplica╚Ťia.

instrument control:
GNU Octave poate comunica cu Arduino prin intermediul interfe╚Ťei seriale, dar nu o poate face ├«n starea ini╚Ťial─â. la fel ca ├«n cazul MatLab, e necesar─â o bibliotec─â extern─â cu instruc╚Ťiuni care s─â-i permit─â citirea datelor seriale. cea pe care am utilizat-o ├«n curs se nume╚Öte instrument control ╚Öi e disponibil─â aici.

biblioteca se instaleaz─â u╚Öor, desc─ârc├ónd fi╚Öierul ╚Öi mut├óndu-l ├«n directorul src (de la source) al GNU Octave. ├«n cazul ├«n care directorul nu exist─â, ├«l po╚Ťi crea pur ╚Öi simplu. urmeaz─â s─â porne╚Öti GNU Octave ╚Öi cu ajutorul browserului de fi╚Öiere din st├ónga ferestrei principale, g─âse╚Öti ╚Öi intrii ├«n directorul src. ultimul pas const─â ├«n introducerea urm─âtoarei comenzi ├«n consola GNU Octave:

>> pkg install instrument-control-0.3.0.tar.gz

instalarea instrument control dureaz─â destul de mult a╚Öa c─â po╚Ťi s─â iei o pauz─â de c├óteva minute.

read_arduino.m:
pentru citirea interfe╚Ťei seriale a Arduino am scris o mic─â buc─â╚Ťic─â de cod ├«n formatul GNU Octave, read_arduino.m care ├«╚Ťi pune la dispozi╚Ťie o func╚Ťie cu ajutorul c─âreia po╚Ťi citi datele ├«ntr-o matrice. presupunem c─â ├«mi doresc s─â citesc tensiunea pe fiecare dintre cele 6 intr─âri analogice ╚Öi s─â ├«i urm─âresc evolu╚Ťia ├«n timp, la intervale de o secund─â.

codul pentru Arduino este urm─âtorul:

void setup () {
  Serial.begin (9600); // <-- read_arduino.m suport─â doar viteza de 9600 bauds
}

void loop () {
  byte port = 0; // <-- am nevoie de o variabila care specifica numarul portului analog
  while (port < 6) { // <-- cel mult voi citi date de la portul 5
    Serial.print (analogRead (port)); // <-- citesc si trimit valoarea citita catre portul serial
    Serial.print ("\t"); // <-- pentru a separa valorile, folosesc caracterul TAB (\t)
    port = port + 1; // <-- trec la portul urmator
  }
  Serial.print ("\n"); // <-- pentru a separa sirurile de date, folosesc caracterul NEW LINE (\n)
  delay (1000); // <-- aștept o secundă pentru a relua ciclul
}

care ar trebui s─â produc─â la fiecare secund─â c├óte o linie cu valori cuprinse ├«ntre 0 ╚Öi 1023, corespunz─âtoare diferen╚Ťei de poten╚Ťial ├«ntre pinul GND ╚Öi pinii de la A0 la A5.

pentru a citi 10 r├ónduri con╚Ťin├ónd cele 6 valori, vei folosi:

>> A = read_arduino ('COM5', 10, 6)
A =

   339   339   326   319   312   324
   328   330   319   313   309   319
   327   329   319   314   310   319
   324   327   317   312   308   318
   323   326   316   311   307   317
   324   327   317   312   309   318
   322   324   314   310   306   315
   323   326   317   312   307   317
   324   327   317   312   308   318
   323   326   316   311   307   317

note de final:
COM5 este portul serial pe care se conecteaz─â pl─âcu╚Ťa mea Arduino. ├«n cazul t─âu, acesta va fi cel mai probabil diferit. verific─â ├«n Device Manager care este portul corect. read_arduino.m func╚Ťioneaz─â ╚Öi pe Linux ╚Öi pe MAC, ├«ns─â ├«n locul COM5 vei folosi denumirea portului corespunz─âtoare platformei. portul serial trebuie s─â fie liber, drept pentru care aminte╚Öte-╚Ťi ca ├«nainte s─â rulezi read_arduino s─â ├«nchizi monitorul serial al Arduino. ca ├«n cazul MathWorks Matlab, fi╚Öierul read_arduino.m ├«n directorul curent pentru ca func╚Ťia s─â devin─â accesibil─â.

bogdan » arduino: senzor de lumin─â cu led

11:20 am on Mar 25, 2018 | #more | tags:

├«n urma rug─âmin╚Ťii profesorului Stamatin, de c├ó╚Ťiva ani ╚Ťin un curs la Facultatea de Fizic─â din M─âgurele. dac─â ini╚Ťial numele «modelare ╚Öi simulare» ascundea ecua╚Ťii matematice ╚Öi metode numerice, recent am ├«nlocuit diferen╚Ťialele cu Arduino, ├«n ova╚Ťiile celor c├ótorva studen╚Ťi care frecventeaz─â cursul. dot─ârile limitate m-au f─âcut s─â devin creativ cu materialele de curs, iar rezultatul mi s-a p─ârut suficient de interesant pentru a-l reproduce aici. a╚Öa c─â:

senzorii de lumin─â domin─â lumea sim╚Ťurilor electronice. cu mici modific─âri, ace╚Ötia pot r─âspunde unei multitudini de ├«ntreb─âri, de la banalul ÔÇŁe lumin─â afar─â?ÔÇŁ, la ÔÇŁce culoare are un obiect?ÔÇŁ sau ÔÇŁla ce distan╚Ť─â am un obstacol ├«n fa╚Ť─â?ÔÇŁ. la prima vedere func╚Ťioneaz─â complex: un fragment de siliciu reac╚Ťioneaz─â la lumina incident─â, modific├ónd o m─ârime electric─â. Einstein a luat premiul Nobel pentru explicarea principiului ├«n 1921, deci trebuie s─â fie complicat. cu toate acestea, tehnologia s-a dezvoltat pe parcursul secolului care a trecut suficient de mult ca s─â putem reface experimentul ├«n buc─ât─ârie.

materiale necesare:

  • un Ardunio, de orice fel, ├«n func╚Ťie de c├ót de familiarizat e╚Öti cu el; la curs l-am folosit pe ─âsta (31 de lei);
  • un led obi╚Önuit, orice culoare ╚Öi orice m─ârime, dar s─â fie un led simplu; ╚Ötii c─â e un led simplu (30 de bani), dac─â e foarte ieftin;
  • dou─â fire pentru a lega ledul la Arduino; mie ├«mi plac astea (3 lei), dar pot fi de orice fel;

pu╚Ťin─â teorie:
un led este un dispozitiv semiconductor, de obicei din siliciu, al c─ârui element activ este vizibil. elementul activ poart─â numele de jonc╚Ťiune, adic─â locul de ├«nt├ólnire pentru dou─â materiale cu propriet─â╚Ťi diferite. ce e important de re╚Ťinut pentru construc╚Ťia de fa╚Ť─â este c─â cele dou─â materiale formeaz─â un sandvi╚Ö cu un mic spa╚Ťiu ├«ntre ele, asemeni unui condensator de la fizic─â. ├«n func╚Ťionarea normal─â, trecerea curentului electric prin acel mic spa╚Ťiu produce lumin─â. cu siguran╚Ť─â ai observat c─â polaritatea e important─â, deoarece lumina ╚Öi circula╚Ťia curentului se produc doar ├«ntr-un singur sens.

ce se ├«nt├ómpl─â ├«n schimb c├ónd polaritatea e inversat─â? lipsa curentului electric duce la acumularea de sarcini electrice pe fe╚Ťele sandvi╚Öului, ├«nc─ârc├ónd condensatorul. cum naturii ├«i plac simetriile, orice raz─â de lumin─â incident─â genereaz─â perechi de sarcini, care se vor deplasa ├«n direc╚Ťii opuse, datorit─â atrac╚Ťiei electrostatice. ajunse pe suprafe╚Ťele sandvi╚Öului, acestea vor sc─âdea sarcina acumulat─â pe condensator, sc─âz├ónd propor╚Ťional ╚Öi tensiunea electric─â.

├«n mod normal, procesele se ├«nt├ómpl─â extrem de repede ╚Öi sunt extrem de mici ca intensitate. dar aici intervine genialitatea oamenilor care au proiectat Arduino: acesta e suficient de rapid ╚Öi suficient de sensibil pentru a face fa╚Ť─â experimentului.

ce se va întâmpla:
Arduino va ├«nc─ârca ledul, aliment├óndu-l invers, dup─â care va num─âra c├ót ├«i ia condesatorului format ├«n jurul jonc╚Ťiunii ledului pentru a se desc─ârca. pentru a repeta experimentul de la curs, vei conecta ledul cu plusul (picioru╚Öul mai lung, anodul) la GND (ground, 0V) ╚Öi minusul (picioru╚Öul mai scurt, catodul) la unul dintre terminalele Arduino, cu excep╚Ťia pinilor 0,1 - care sunt responsabili pentru comunicarea serial─â ╚Öi pinul 13, care are deja un led conectat intern ╚Öi care te va ├«ncurca. eu am ales pinul 2.

├«n preg─âtirea Arduino, am definit un loc ├«n memorie pentru stocarea informa╚Ťiilor primite de la led. tipul de date folosit va fi ├«ntreg (int), num─âr├ónd c├óte perioade de timp condensatorul a fost ├«nc─ârcat. pentru a fi accesibil─â de oriunde, defini╚Ťia se va afla ├«n afara ╚Öi ├«naintea celor dou─â func╚Ťii speciale Arduino, setup ╚Öi loop.

int value; // <- asa definesc un loc in memorie, int este tipul, iar value este numele
// pentru ca am definit-o în afara setup și loop, voi putea să o accesez de oriunde, prin nume
void setup() {}
void loop() {}

pentru citirea informa╚Ťiilor, am folosit interfa╚Ťa serial─â a Arduino, care va fi ini╚Ťializat─â prin:

int value;
void setup() {
  Serial.begin(9600); // <- aici initializez conexiunea seriala cu viteza de 9600 caractere / s
}
void loop() {}

periodic, am încărcat ledul pentru un interval de timp. experimental am ales 1ms.

int value;
void setup() {
  Serial.begin(9600);
}
void loop() {
  pinMode(2, OUTPUT); // <- aici definesc pinul 2 ca fiind pin de iesire
  digitalWrite(2, HIGH); // <- setez tensiunea pe pinul 2 la tensiunea de alimentare a Arduino
  delay(1); // <- astept 1ms, sa incarc condensatorul ledului
}

am m─âsurat ├«n c├ót timp tensiunea la bornele ledului scade sub un anumit prag. aici a╚Ö fi putut s─â folosesc convertorul analog-digital din Arduino, dar ├«n unele situa╚Ťii este prea lent. a╚Öa c─â am folosit proprietatea unui pin digital configurat ca intrare de a-╚Öi schimba starea ├«n jurul jum─ât─â╚Ťii tensiunii de alimentare a Arduino. astfel, dac─â tensiunea la intrare scade sub 2.5V fa╚Ť─â de GND (pentru un Arduino alimentat la 5V), valoarea citit─â intern va fi LOW, ├«n timp ce dac─â tensiunea cre╚Öte peste 2.5V, valoarea citit─â va fi HIGH.

pentru a determina ├«n c├ót timp tensiunea la bornele ledului scade, am verificat la intervale scurte de timp dac─â a sc─âzut. dac─â a sc─âzut, trimit prin conexiunea serial─â valoarea ├«nregistrat─â, altfel, mai a╚Ötept pu╚Ťin timp ╚Öi verific din nou. experiment├ónd, am folosit ca timp de a╚Öteptare 40uS.

int value;
void setup() {
  Serial.begin(9600);
}
void loop() {
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
  delay(1);
  pinMode(2, INPUT);
  value = 0; // <- aici resetez ce stochez în memorie
  while(digitalRead(2) == HIGH) { // <- citesc pinul 2 si verific daca tensiunea depasește pragul
    delayMicroseconds(40); // <- daca e peste prag, lumina e prea slabă și aștept 40uS
    value = value + 1; // <- cresc cu o unitate valoarea stocat─â
  }
  // <- aici tensiunea la bornele ledului a scazut sub prag
  Serial.println(value); // <- așa că trimit valoarea prin conexiunea serială
}

├«n func╚Ťie de led ╚Öi de condi╚Ťiile de iluminare, valorile primite de calculator sunt uneori negative. acest lucru se ├«nt├ómpl─â deoarece num─ârul de repet─âri dep─â╚Öe╚Öte valoarea maxim─â care poate fi stocat─â ├«ntr-un segment de memorie de tip ├«ntreg. pentru a preveni aceast─â situa╚Ťie, am introdus o limitare la 255 a num─ârului de cicluri pentru care verificarea are loc:

int value;
void setup() {
  Serial.begin(9600);
}
void loop() {
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
  delay(1);
  pinMode(2, INPUT);
  value = 0;
  while((digitalRead(2) == HIGH) && (value < 255)) { // <- verific în plus dacă valoarea stocată e sub 255
    delayMicroseconds(40);
    value = value + 1;
  }
  Serial.println(value);
}

note de final:
ledul este sensibil la acela╚Öi tip de lumin─â pe care o emite. folosind acest principiu, po╚Ťi foarte u╚Öor s─â-l transformi ├«ntr-un senzor de culoare. de asemenea, un led are de obicei o lentil─â care dirijeaz─â razele de lumin─â, limit├óndu-i astfel c├ómpul vizual, la fel ca ├«n cazul emisiei. folosind aceast─â informa╚Ťie, po╚Ťi adapta foarte u╚Öor un led pentru a m─âsura distan╚Ťa.

bogdan » php string output speed test

11:54 pm on Feb 14, 2017 | #more | tags:

during the development of a new resource-sensitive project, i wondered what is the best PHP string output method and thus compared the following:

<?php
/*  A: */	printf ('some value %d != %d' . "\n", $c, $c+1); 
/*  B: */	vprintf ('some value %d != %d' . "\n", [ $c, $c+1 ]); 
/*  C: */	vprintf ('some value %d != %d%s', [ $c, $c+1, "\n" ]); 
/*  D: */	echo sprintf ('some value %d != %d' . "\n", $c, $c+1); 
/*  E: */	echo vsprintf ('some value %d != %d' . "\n", [ $c, $c+1 ]); 
/*  F: */	echo vsprintf ('some value %d != %d%s', [ $c, $c+1, "\n" ]);
/*  G: */	echo 'some value ' . $c . ' != ' . ($c+1) . "\n";
/*  H: */	echo "some value $c != " . ($c+1) . "\n";
/*  I: */	?>some value <?php echo $c; ?> != <?php echo $c+1; ?>
<?php ?>

each statement was run inside a for loop, for one million cycles, for a total number of five times. the results were as follows:

A B C D E F G H I
0.4260 0.5836 0.6412 0.4333 0.5896 0.6781 0.4449 0.4182 0.0361
0.4220 0.6012 0.6631 0.4302 0.6210 0.6805 0.4385 0.4100 0.0361
0.4205 0.6083 0.6674 0.4306 0.6245 0.6935 0.4379 0.4168 0.0378
0.4364 0.6098 0.6697 0.4456 0.6752 0.7455 0.4530 0.4134 0.0361
0.4299 0.5964 0.6594 0.4384 0.5793 0.6538 0.4485 0.4185 0.0365

on average, the best I is 11.37 times faster than the next, followed by H, A, D, G, B, E, C and F, which is worst, 18.90 times slower than I.

bogdan » ├«ntotdeauna ├«n al 12-lea ceas!

11:46 am on Nov 29, 2016 | #more | tags:

Cu toate astea, dec├ót s─â-┼úi dai ochii sc├órbit peste cap o via┼ú─â-ntreag─â, ├«n a┼čteptarea unui salvator, mai bine ├«┼úi arunci privirea-n oglind─â ┼či poate descoperi ce st─â ├«n puterile tale.

M─â enerveaz─â articolele astea: iau o idee bun─â, o minimizeaz─â ╚Öi o transform─â ├«n demagogie electoral─â. Puterea de a face schimb─âri st─â ├«ntr-adev─âr ├«n fiecare dintre noi, doar c─â e insignifiant─â ├«n urma aia l─âsat─â de ╚Ötampil─â pe buletinul de vot. E pur ╚Öi simplu o delegare a r─âspunderii c─âtre un grup de oameni care inevitabil vor fi corup╚Ťi de sistem. Pentru c─â sistemul a╚Öa a fost g├óndit ╚Öi nu a dat gre╚Ö niciodat─â ├«n 27 de ani de c├ónd a fost reformat.

  • Vrem transparen╚Ť─â total─â? C├ó╚Ťi dintre noi au trimis o cerere prin legea 544/2001?
  • Vrem industrie modern─â? C├ó╚Ťi dintre noi, care au afaceri, ╚Öi-au rupt de la gur─â aleg├ónd o ma╚Öin─â ieftin─â sau transportul ├«n comun ├«n locul unei ma╚Öini scumpe pentru a investi diferen╚Ťa ├«n echipamente mai performante?
  • Vrem agricultura micilor fermieri? C├ó╚Ťi dintre noi, care au terenuri mici, le muncesc sau le dau ├«n arend─â? C├ó╚Ťi ne-am g├óndit s─â ne asociem ╚Öi s─â ne dezvolt─âm ├«mpreun─â cu vecinii no╚Ötri?
  • Vrem ├«nv─â╚Ť─âm├ónt performant? C├ó╚Ťi dintre noi s-au implicat activ ╚Öi realist ├«n adaptarea programei ╚Öcolare ╚Öi a modului de predare ├«n ╚Öcolile ├«n care ├«nva╚Ť─â copiii no╚Ötri? C├ó╚Ťi dintre noi, ca profesioni╚Öti, ╚Öi-au rupt din timp s─â ├«ncerce s─â transmit─â informa╚Ťia acumulat─â?
  • Vrem cultura vie? C├ó╚Ťi dintre noi am mers ├«n weekend la un muzeu sau la o pies─â de teatru, ├«n loc s─â mergem la Mall? C├ó╚Ťi dintre noi au ├«ncercat s─â ├«n╚Ťeleag─â ce-au v─âzut?
  • Vrem s─ân─âtate public─â? C├ó╚Ťi dintre noi ne facem un control periodic? C├ó╚Ťi dintre noi ├«╚Öi vaccineaz─â copii sau ├«i duc la dentist? C├ó╚Ťi dintre noi am f─âcut pl├óngeri la Colegiul Medicilor?
  • Vrem transport rapid? C├ó╚Ťi dintre noi mergem cu ma╚Öina cu toate locurile ocupate? C├ó╚Ťi dintre noi respect─â regulile de circula╚Ťie?
  • Vrem s─â salv─âm mediul? C├ó╚Ťi dintre noi nu arunc─â gunoaie pe jos? C├ó╚Ťi dintre noi economisim apa sau energia electric─â? C├ó╚Ťi dintre noi nu merg cu ma╚Öina, 500 de metri, pentru mici cump─âr─âturi?
  • Vrem ca Rom├ónia s─â arate bine ├«n lume? C├ó╚Ťi dintre noi se poart─â civilizat ╚Öi cu bun sim╚Ť c├ónd ie╚Öim din ╚Ťar─â?
  • Vrem mai pu╚Ťin─â corup╚Ťie? C├ó╚Ťi dintre noi nu au dat sau nu au luat ╚Öpag─â?
  • Vrem mai pu╚Ťin clientelism politic? C├ó╚Ťi dintre noi, care lucreaz─â ├«n companiile abonate la contracte publice, s-au pl├óns?

Schimbarea nu e inclus─â ├«n tu╚Öul unei ╚Ötampile. Salvarea nu vine de la un acronim. Bun─âstarea nu vine dintr-un set de legi emise, redactate ╚Öi implementate de incompeten╚Ťi populari. Solu╚Ťia va fi ├«ntotdeauna la ├«ndem├óna fiec─âruia dintre noi, ├«n ac╚Ťiunile noastre zilnice.

bogdan » inocen╚Ť─â

10:13 am on Nov 27, 2016 | #more | tags:

Vreau s─â fiu un om bun.
Care e p─ârerea ta?
Sunt?
Da. Ești. Mie așa mi se pare. Eu nu stau de vorbă cu oameni răi.

bogdan » what is more beautiful

09:12 am on Nov 25, 2016 | #more | tags:

What is more beautiful, my love? Love lost or love found? Don't laugh at me, my love. I know it, I'm awkward and naive, when it comes to love, and I ask questions straight out of a pop song. This doubt overwhelms me and undermines me, my love. To find or to lose? All around me people don't stop yearning. Did they lose or did they find? I can't say. An orphan has no way of knowing. An orphan lacks a first love. The love for his mama and papa. That's the source of his awkwardness, his naivete. You said to me, on that deserted beach in California: "you can touch my legs." But I didn't do it. There, my love, is love lost. That's why I've never stopped wondering, since that day: where have you been? And where you are now? And you, shining gleam of my misspent youth, did you lose or did you find? I don't know. And I will never know. I can't even remember your name, my love. And I don't have the answer. But this is how I like to imagine it, the answer. In the end, my love, we have no choice. We have to find.

bogdan » nu sunt antreprenor

12:50 am on Jan 11, 2016 | #more | tags:

nu ├«ndr─âznesc s─â spun despre mine c─â sunt antreprenor. nu m─â ridic la ├«n─âl╚Ťimea standardelor stabilite ├«n literatura de specialitate. nici pe departe. nu m-am dezvoltat personal ╚Öi nici nu am ├«nv─â╚Ťat s─â fac business.

sunt aproape doi ani de c├ónd ├«mi asum riscuri pentru a-mi construi propriul drum ╚Öi nu pot s─â spun exact c─â mi-a reu╚Öit ╚Öi nici c─â am e╚Öuat. pentru c─â ├«n via╚Ť─â, am ├«nv─â╚Ťat, lucrurile nu sunt absolute.

am pornit un start-up pentru c─â-mi place s─â visez ╚Öi a╚Ö vrea, la un moment dat, s─â-mi urmez visul. felul ─âsta de activitate ├«mi va pune la dispozi╚Ťie resursele de care am nevoie s─â visez cu ochii deschi╚Öi. am ├«ncercat ╚Öi alte metode.

am fost angajat. ╚Öi de╚Öi am avut parte e oameni extraordinari care au fost al─âturi de mine s─â m─â ├«ndrume ╚Öi de la care am ├«nv─â╚Ťat o mul╚Ťime de lucruri, nu era locul meu acolo. pentru c─â un loc de munc─â ├«╚Ťi ia ceea ce ai tu mai de pre╚Ť. la mine era creativitatea de care aveam nevoie s─â visez. mi-au oferit ├«n schimb bani ╚Öi lini╚Öte. n-a fost suficient.

am fost finan╚Ťat. ╚Öi din nou, oamenii cu care am pornit la drum au fost minuna╚Ťi ╚Öi din nou am ├«nv─â╚Ťat de la ei o mul╚Ťime de lucruri, dar din nou locul meu nu era acolo. un finan╚Ťator te las─â s─â faci ceea ce-╚Öi dore╚Öti. dar ├«╚Ťi impune limite. pe care la ├«nceput nu le observi sau crezi c─â po╚Ťi s─â le ignori, p├ón─â c├ónd libertatea ta dispare. imagineaz─â-╚Ťi c─â te oblig─â cineva s─â visezi ├«n fiecare sear─â vacan╚Ťe exotice ╚Öi ziua, un om care nu poate s─â viseze te auditeaz─â pentru a-╚Ťi verifica calitatea viselor. mi-a oferit ├«n schimb bani ╚Öi o parte din vis. n-a fost suficient.

sunt propriul meu angajat. sunt creativ pentru clien╚Ťi ├«n limita pe care mi-o permit f─âr─â s─â-mi afecteze visul. ├«mi impun limite la vis pentru a le putea dep─â╚Öi. e greu ╚Öi muncesc de cel pu╚Ťin dou─â ori mai mult dec├ót am muncit ├«n oricare dintre situa╚Öiile anterioare. n-am avut vacan╚Ť─â de c├ónd am ├«nceput. am oameni care depind de mine ╚Öi de care trebuie s─â am grij─â pentru c─â ei au grij─â de visul meu. mi-am oferit libertatea de a visa ╚Öi par╚Ťial bani. s─â-mi ├«mplinesc visul a devenit o problem─â de timp.

ce-am ├«nv─â╚Ťat ├«n aproape doi ani de indenden╚Ť─â? c─â trebuie s─â munce╚Öti foarte mult ╚Öi trebuie s─â fii dedicat visului t─âu. c─â la un moment dat trebuie s─â g─âse╚Öti oameni la fel de dedica╚Ťi ca ╚Öi tine ╚Öi s─â faci tot posibilul s─â-i p─âstrezi. c─â ├«ntotdeauna primul r─âspuns corect la o ├«ntrebare este ┬źnu┬╗. c─â e important s─â fii sincer fa╚Ť─â de clien╚Ťii, furnizorii ╚Öi angaja╚Ťii cu care ├«╚Ťi dore╚Öti s─â lucrezi: nu trebuie s─â epatezi ╚Öi nici s─â aplici tehnici speciale de negociere. c─â ai nevoie de avocat ╚Öi contabil. ╚Öi din nefericire, c─â Mr. Burns are dreptate:

Family, religion, friendship. These are the three demons you must slay if you wish to succeed in business.
-- Charles Montgomery ÔÇŁMontyÔÇŁ Burns

green-rocket

bogdan » bypass

12:08 am on Sep 14, 2014 | #more | tags:

sunt m├óndru c─â sunt absolvent de matematic─â ╚Öi ├«i voi fi pentru eternitate recunosc─âtor domnului profesor st─ânescu pentru c─â m-a ├«ndrumat pe acest drum. recomand cu c─âldur─â ╚Öi sinceritate acest parcurs oric─ârui elev de liceu, viitor absolvent, care vrea s─â ├«n╚Ťeleag─â cu adev─ârat ceva din via╚Ť─â.

s─â nu m─â ├«n╚Ťelegi gre╚Öit. corpul profesoral este ├«n majoritate viciat: slab preg─âtit, corup ╚Öi amoral. ├«ns─â ╚Öcoala rom├óneasc─â de ╚Ötiin╚Ťe exacte ÔÇô slab influe╚Ťat─â de retorica partidului, ├«n antitez─â cu cea de ╚Ötiin╚Ťe umaniste ÔÇô ╚Öi-a pus amprenta exact acolo unde trebuie, ├«n orgoliul nem─ârginit al urma╚Öilor lor, actualii conferen╚Ťiari ╚Öi profesori universitari. ignoran╚Ťa ╚Öi indiferen╚Ťa lor fa╚Ť─â de subiectul predat fiind suplinit─â de canonul metodei de predare, l─âsat mo╚Ötenire de genera╚Ťiile anterioare.

aceast─â metod─â este singurul aspect care delimiteaz─â facultatea de matematic─â de noroiul ├«ntregului ├«nv─â╚Ť─âm├ónt superior rom├ónesc ╚Öi care, asemeni unui vaccin dureros ╚Öi generos ├«n complica╚Ťii, te protejeaz─â ╚Öi te ├«nt─âre╚Öte pe parcursul existen╚Ťei.

cheia ├«ntregului proces este trecerea obligatorie prin gre╚Öelile pe care genera╚Ťii ├«ntregi de filosofi ╚Öi matematicieni le-au f─âcut prin studiul demonstra╚Ťiilor afirma╚Ťiilor lor omonime. ├«n acest fel, analizarea argumentelor fiec─âruia ajut├óndu-te s─â integrezi ├«n personalitatea ta buc─â╚Ťele din acel om, experiment├ónd direct, mai ales ├«n timpul examenelor aparent ilogice, dezam─âgirilile ╚Öi durerea acelui om, dar ╚Öi euforia descoperirii.

pentru c─â ├«n via╚Ť─â, drumul e mult mai important dec├ót destina╚Ťia. ╚Öi orice scurt─âtur─â pe care o alegem ne priveaz─â de experien╚Ťa c─âl─âtoriei, a obstacolelor ╚Öi piedicilor pe care le ├«nt├ólnim pe parcurs, a lucrurilor care ne ajut─â s─â ne cl─âdim caracterul ╚Öi s─â apreciem destina╚Ťia.

the Apollo 1 Crew

Pe 27 ianuarie 1967, Gus Grissom, Ed White și Roger Chaffee (de la stânga la dreapta) se pregăteau pentru prima misiune Apollo. Capsula în care aceștia se aflau a fost distrusă de un incediu în timpului unui test înainte de zbor. Doi ani și șase luni mai târziu, Armstrong și Aldrin pășeau pe Lună.

bogdan » 28 aprilie – diferen╚Ťe de gen

08:41 pm on Apr 28, 2014 | #more | tags:

Diferen╚Ťele dintre sexe sunt exprimate la nivel celular. Viitorul ne rezerv─â medicamente specifice pentru femei, respectiv b─ârba╚Ťi.

Un articol ╚Ötiin╚Ťific publicat ├«n revista Nature[1] studiaz─â procesul prin care cromozomul Y, determinant pentru stabilirea genului masculin ├«n cadrul majorit─â╚Ťii mamiferelor, a fost mic╚Öorat pe parcursul a 300 de milioane de ani de evolu╚Ťie, estim├ónd o stopare a acestui proces ├«nc─â de acum 25 de milioane de ani. Cauza opririi acestui proces are originea ├«ntr-un nucleu de 12 gene, care nu influen╚Ťeaz─â aparatul reproduc─âtor masculin, ci ╚Ťesuturi prezente ├«n inim─â sau celulele sangvine, transform├ónd micu╚Ťul cromozom ├«ntr-unul dintre gadget-urile genetice esen╚Ťiale pentru supravie╚Ťuire fiind favorizat de procesului evolutiv. Consecin╚Ťa direct─â a acestor descoperiri este diferen╚Ťa impus─â de gen ├«n liniile celulare ale indivizilor aceleia╚Öi specii ╚Öi invalid├ónd orice model celular unisex pentru ╚Ťesuturile afectate. Efectul procedurilor medicale specifice ╚Öi al medicamentelor devine imprevizibil pentru produsele ╚Öi protocoalele derivate din cercet─ârile bazate pe modelul ÔÇŁegalit─â╚Ťii de gen celulareÔÇŁ. Cu alte cuvinte, viitorul apropiat ne va aduce medicamente specifice pentru b─ârba╚Ťi ╚Öi femei [surs─â].

X and Y chromosomes

├Än aceea╚Öi not─â, ╚Öoarecii de laborator sunt mai stresa╚Ťi atunci c├ónd sunt utiliza╚Ťi de c─âtre cercet─âtorii de gen masculin, duc├ónd la devierea rezultatelor experimentelor ├«n care sunt folosi╚Ťi [surs─â]. Mai mult, mirosul cercet─âtorilor b─ârba╚Ťi cre╚Öte toleran╚Ťa la durere a roz─âtoarelor [surs─â], compromi╚Ť├ónd rezultatele ob╚Ťinute ├«n urma diferitelor teste.

O căpușă este cel mai rapid animal de pe planetă. Viteza la scara umană a acestui arahnid ar fi de 2,000 km/h.

Micul arahnid, Paratarsotomus macropalpis, se poate deplasa cu o vitez─â de 322 lungimi de corp ├«ntr-o secund─â ├«n compara╚Ťie cu un ghepard care alearg─â cu numai 16 lungimi de corp pe secund─â. Studiul c─âpu╚Öei este interesant pentru determinarea principiilor mecanice care stau la baza vitezei incredibile de mi╚Öcare a picioarelor micului organism, fiecare picior ating├ónd solul de 135 de ori ├«ntr-o secund─â, lucru extrem de util de implementat ├«n viitorii mini-, micro- ╚Öi nano- robo╚Ťi [surs─â].

--

1. Bellott, D. W. et al. Nature 508, 494ÔÇô499 (2014).

aceast sait folose╚Öte cookie-uri pentru a ├«mbun─ât─â╚Ťi experien╚Ťa ta, ca vizitator. ├«n acela╚Öi scop, acest sait utilizeaz─â modulul Facebook pentru integrarea cu re╚Ťeaua lor social─â. po╚Ťi accesa aici politica mea de confiden╚Ťialitate.