Compressão de bytes

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Compressão de bytes

Mensagempor Diego_Oliveira » 09 Nov 2009 12:42

Minha ideia é a seguinte:

-Tenho de amazenar temperaturas de 0 a 50°C, em uma memoria eeprom do tipo "I2C", 24c512, são muitos dados digasse de passagem, mas são armazenados em sequencia.

-As temperaturas vão de 0 a 50 sendo 51 a indicação de aberto ou defeito.

Por se tratar de informaçoes de 0 a 51, e um byte armazena de 0 ... 255 pensei porque não comprimilos, unindo duas informaçoes em um byte só...

Claro neste meu caso eu não tenho grande ideia masacho que talvez conseguiria unir 3 talvez 4 mas duas informaçoes já estariam de bom tamanho.

Procurei na internet mas não achei nada especifico na area de microcontroladores, porém na area de computadores codecs ETC tem muita coisa, li algum materias porém não cheguei a grandes conclusoes !

Grato !!!!
Avatar do usuário
Diego_Oliveira
Nibble
 
Mensagens: 79
Registrado em: 05 Abr 2008 15:18
Localização: Rio Grande do Sul

Mensagempor Sergio38br » 09 Nov 2009 13:01

Boas, vc vai receber estes dados em dec. ou hex?

[ ]'s
Sergio
Avatar do usuário
Sergio38br
Word
 
Mensagens: 759
Registrado em: 22 Nov 2007 13:39
Localização: São Paulo - SP

Mensagempor Diego_Oliveira » 09 Nov 2009 13:08

Não, é bem mais simples do que parece Sergio38br,

Esses dados o próprio microcontrolador vai varrer os sensores e armazenar...

Depois ele envia via USB mas ai já enviaria "desconpactado".

A ideia é só economizar ums bytes de memoria, pois são varios sensores e tenho de armazena-los de hora em hora...
Avatar do usuário
Diego_Oliveira
Nibble
 
Mensagens: 79
Registrado em: 05 Abr 2008 15:18
Localização: Rio Grande do Sul

Mensagempor Diego_Oliveira » 09 Nov 2009 13:15

Desculpa,

É em decimais não tinha entendido direito por causa da abreviação de dec. perdão...
Avatar do usuário
Diego_Oliveira
Nibble
 
Mensagens: 79
Registrado em: 05 Abr 2008 15:18
Localização: Rio Grande do Sul

Mensagempor Alesandro F Zagui » 09 Nov 2009 13:29

Você vai ter que criar o algoritmo pra isso na mão.

Como sua informacao vai de 0 a 51, você vai precisar de 6 bits pra armazenar cada informação.

suponhamos o seguinte:

AAAAAA - BITS DO PRIMEIRO VALOR
BBBBBB - BITS DO SEGUNDO VALOR
CCCCCC- BITS DO TERCEIRO VALOR
DDDDDD- BITS DO QUARTO VALOR

Hoje provavelmente vc armazena assim:

endereco 1
00AAAAAA
endereço 2
00BBBBBB
endereço 3
00CCCCCC
endereço 4
00DDDDDD

Voce teria que criar um rotina que organizasse os bits assim:

endereço 1
AAAAAABB
endereço 2
BBBBCCCC
endereço 3
CCDDDDDD


Antes precisa de 4 bytes e agora precisa de 3 pra armazenar a mesma informação.
Editado pela última vez por Alesandro F Zagui em 10 Nov 2009 08:08, em um total de 2 vezes.
Alesandro Freire Zagui
Alesandro F Zagui
Byte
 
Mensagens: 154
Registrado em: 12 Mai 2009 11:03
Localização: Campo Mourao, Pr

Mensagempor Alesandro F Zagui » 09 Nov 2009 13:32

Qual PIC você está usando??

Porque não salva na eeprom dele, ou na própria memória flash do PIC?
Alesandro Freire Zagui
Alesandro F Zagui
Byte
 
Mensagens: 154
Registrado em: 12 Mai 2009 11:03
Localização: Campo Mourao, Pr

Mensagempor Diego_Oliveira » 09 Nov 2009 13:40

Alesandro F Zagui escreveu:Qual PIC você está usando??

Porque não salva na eeprom dele, ou na própria memória flash do PIC?


PIC 16f876A + 24LC512

é que são da ordem de 100 mil leituras, a 24lc512 tem 64K bytes, mas se eu colocasse 2 informaçoes em um byte, atenderia..

A memoria interna já armazena outras coisas...
Avatar do usuário
Diego_Oliveira
Nibble
 
Mensagens: 79
Registrado em: 05 Abr 2008 15:18
Localização: Rio Grande do Sul

Mensagempor Jorge_Francisco » 09 Nov 2009 13:45

Eu conheço alguns algorimos de compressão : LZR, Huffman, etc. Mas usar num PIC, meio chatinho, tem um carinha aqui que fez um algoritmo otimizado para PIC, mas nem sei onde colocou.

Vlw
Avatar do usuário
Jorge_Francisco
Dword
 
Mensagens: 1009
Registrado em: 12 Out 2006 09:53
Localização: Rio de Janeiro

Mensagempor Djalma Toledo Rodrigues » 09 Nov 2009 13:51

t1
Rotaciona a Esquerda 2 x ---> t100
+ t2 -----------------------------> t1t2
Rotaciona a Esquerda 2 x ---> t1t200
+ t3 ------------------------------> t1t2t3




----------------------------
Cabem 3 de 51°C redondinho.
51 ? Uma boa idéia! l_l? l_l?
.
Editado pela última vez por Djalma Toledo Rodrigues em 09 Nov 2009 18:38, em um total de 6 vezes.
Avatar do usuário
Djalma Toledo Rodrigues
Dword
 
Mensagens: 2334
Registrado em: 03 Ago 2008 13:22

Mensagempor Sergio38br » 09 Nov 2009 13:56

Me diga uma coisa, qual a taxa de compressão que vc quer?? tem uma forma de quardar a temperatura em BCD que pode reduzir em 2 para 1:

ex. 35

em hex 33 e 35 , subtraia 30 de cada desloque o primeiro 4 casa a esquerda e some com o segundo, pronto vc tem 35 em BCD

[ ]'s
Sergio
Avatar do usuário
Sergio38br
Word
 
Mensagens: 759
Registrado em: 22 Nov 2007 13:39
Localização: São Paulo - SP

Mensagempor MOR_AL » 09 Nov 2009 15:23

Acredito que a determinação do período de uma hora tenha sido por ser uma escolha conveniente. Então, por conveniência, porque que você não monitora a temperatura de 2 em 2 horas?
MOR_AL
"Para o triunfo do mal só é preciso que os bons homens não façam nada." Edmund Burke.
"Nunca discutas com pessoas estúpidas. Elas irão te arrastar ao nível delas e vencê-lo por possuir mais experiência em ser ignorante". Mark Twain
Avatar do usuário
MOR_AL
Dword
 
Mensagens: 2934
Registrado em: 19 Out 2006 09:38
Localização: Mangaratiba - RJ

Mensagempor Diego_Oliveira » 09 Nov 2009 15:28

MOR_AL escreveu:Acredito que a determinação do período de uma hora tenha sido por ser uma escolha conveniente. Então, por conveniência, porque que você não monitora a temperatura de 2 em 2 horas?
MOR_AL


Na verdade não é por conveniencia, isso foi pedido pelo cliente, eu até tentei convencer do contrario porém realmente é necessário de 1 em 1 hora....
Avatar do usuário
Diego_Oliveira
Nibble
 
Mensagens: 79
Registrado em: 05 Abr 2008 15:18
Localização: Rio Grande do Sul

Mensagempor MOR_AL » 09 Nov 2009 17:19

Acho que a sugestão do Alesandro F Zagui é a que concentra mais os dados sem perder informação, porém ainda assim ficaria fora de sua necessidade:
Você dispõe de 64kB.
Você quer armazenar 100k valores compreendidos entre 0 e 51.
Com a sugestão do Alesandro F Zagui, você comprimiria os 100k valores em X bytes, onde:
x = 100kB /(1 + 1/3) = 75kB..... Ainda maior que 64kB. :!:
Eu não saberia como reduzir ainda mais sem: alterar o hardware, reduzir o período entre a transferência dos dados ao PC, ou perder informação.
Lamento...
MOR_AL
"Para o triunfo do mal só é preciso que os bons homens não façam nada." Edmund Burke.
"Nunca discutas com pessoas estúpidas. Elas irão te arrastar ao nível delas e vencê-lo por possuir mais experiência em ser ignorante". Mark Twain
Avatar do usuário
MOR_AL
Dword
 
Mensagens: 2934
Registrado em: 19 Out 2006 09:38
Localização: Mangaratiba - RJ

Mensagempor ivan » 09 Nov 2009 20:49

De uma olhada nas rotinas compress e expand. Se vc tiver um compilador C para o PIC q está usando, testa pra ver o tamanho que as rotinas irão ocupar.
Como a compressão é maior com a repetição de caracteres, o seu range de valores é pequeno e com muitas leituras, pode ser caiba uma rotina de compressão junto com o seu código.

Apenas uma sugestão.

http://marknelson.us/1989/10/01/lzw-data-compression/


[code]

/*******************************************************************
**
** Copyright (c) 1989 Mark R. Nelson
**
** LZW data compression/expansion demonstration program.
**
** April 13, 1989
**
** Minor mods made 7/19/2006 to conform with ANSI-C - prototypes, casting,
** and argument agreement.
**
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BITS 12 /* Setting the number of bits to 12, 13*/
#define HASHING_SHIFT (BITS-8) /* or 14 affects several constants. */
#define MAX_VALUE (1 << BITS) - 1 /* Note that MS-DOS machines need to */
#define MAX_CODE MAX_VALUE - 1 /* compile their code in large model if*/
/* 14 bits are selected. */
#if BITS == 14
#define TABLE_SIZE 18041 /* The string table size needs to be a */
#endif /* prime number that is somewhat larger*/
#if BITS == 13 /* than 2**BITS. */
#define TABLE_SIZE 9029
#endif
#if BITS <= 12
#define TABLE_SIZE 5021
#endif

void *malloc();

int *code_value; /* This is the code value array */
unsigned int *prefix_code; /* This array holds the prefix codes */
unsigned char *append_character; /* This array holds the appended chars */
unsigned char decode_stack[4000]; /* This array holds the decoded string */

/*
* Forward declarations
*/
void compress(FILE *input,FILE *output);
void expand(FILE *input,FILE *output);
int find_match(int hash_prefix,unsigned int hash_character);
void output_code(FILE *output,unsigned int code);
unsigned int input_code(FILE *input);
unsigned char *decode_string(unsigned char *buffer,unsigned int code);

/********************************************************************
**
** This program gets a file name from the command line. It compresses the
** file, placing its output in a file named test.lzw. It then expands
** test.lzw into test.out. Test.out should then be an exact duplicate of
** the input file.
**
*************************************************************************/

main(int argc, char *argv[])
{
FILE *input_file;
FILE *output_file;
FILE *lzw_file;
char input_file_name[81];

/*
** The three buffers are needed for the compression phase.
*/
code_value=(int*)malloc(TABLE_SIZE*sizeof(int));
prefix_code=(unsigned int *)malloc(TABLE_SIZE*sizeof(unsigned int));
append_character=(unsigned char *)malloc(TABLE_SIZE*sizeof(unsigned char));
if (code_value==NULL || prefix_code==NULL || append_character==NULL)
{
printf("Fatal error allocating table space!\n");
exit(-1);
}
/*
** Get the file name, open it up, and open up the lzw output file.
*/
if (argc>1)
strcpy(input_file_name,argv[1]);
else
{
printf("Input file name? ");
scanf("%s",input_file_name);
}
input_file=fopen(input_file_name,"rb");
lzw_file=fopen("test.lzw","wb");
if (input_file==NULL || lzw_file==NULL)
{
printf("Fatal error opening files.\n");
exit(-1);
};
/*
** Compress the file.
*/
compress(input_file,lzw_file);
fclose(input_file);
fclose(lzw_file);
free(code_value);
/*
** Now open the files for the expansion.
*/
lzw_file=fopen("test.lzw","rb");
output_file=fopen("test.out","wb");
if (lzw_file==NULL || output_file==NULL)
{
printf("Fatal error opening files.\n");
exit(-2);
};
/*
** Expand the file.
*/
expand(lzw_file,output_file);
fclose(lzw_file);
fclose(output_file);

free(prefix_code);
free(append_character);
}

/*
** This is the compression routine. The code should be a fairly close
** match to the algorithm accompanying the article.
**
*/

void compress(FILE *input,FILE *output)
{
unsigned int next_code;
unsigned int character;
unsigned int string_code;
unsigned int index;
int i;

next_code=256; /* Next code is the next available string code*/
for (i=0;i<TABLE_SIZE;i++) /* Clear out the string table before starting */
code_value[i]=-1;

i=0;
printf("Compressing...\n");
string_code=getc(input); /* Get the first code */
/*
** This is the main loop where it all happens. This loop runs util all of
** the input has been exhausted. Note that it stops adding codes to the
** table after all of the possible codes have been defined.
*/
while ((character=getc(input)) != (unsigned)EOF)
{
if (++i==1000) /* Print a * every 1000 */
{ /* input characters. This */
i=0; /* is just a pacifier. */
printf("*");
}
index=find_match(string_code,character);/* See if the string is in */
if (code_value[index] != -1) /* the table. If it is, */
string_code=code_value[index]; /* get the code value. If */
else /* the string is not in the*/
{ /* table, try to add it. */
if (next_code <= MAX_CODE)
{
code_value[index]=next_code++;
prefix_code[index]=string_code;
append_character[index]=character;
}
output_code(output,string_code); /* When a string is found */
string_code=character; /* that is not in the table*/
} /* I output the last string*/
} /* after adding the new one*/
/*
** End of the main loop.
*/
output_code(output,string_code); /* Output the last code */
output_code(output,MAX_VALUE); /* Output the end of buffer code */
output_code(output,0); /* This code flushes the output buffer*/
printf("\n");
}

/*
** This is the hashing routine. It tries to find a match for the prefix+char
** string in the string table. If it finds it, the index is returned. If
** the string is not found, the first available index in the string table is
** returned instead.
*/

int find_match(int hash_prefix,unsigned int hash_character)
{
int index;
int offset;

index = (hash_character << HASHING_SHIFT) ^ hash_prefix;
if (index == 0)
offset = 1;
else
offset = TABLE_SIZE - index;
while (1)
{
if (code_value[index] == -1)
return(index);
if (prefix_code[index] == hash_prefix &&
append_character[index] == hash_character)
return(index);
index -= offset;
if (index < 0)
index += TABLE_SIZE;
}
}

/*
** This is the expansion routine. It takes an LZW format file, and expands
** it to an output file. The code here should be a fairly close match to
** the algorithm in the accompanying article.
*/

void expand(FILE *input,FILE *output)
{
unsigned int next_code;
unsigned int new_code;
unsigned int old_code;
int character;
int counter;
unsigned char *string;

next_code=256; /* This is the next available code to define */
counter=0; /* Counter is used as a pacifier. */
printf("Expanding...\n");

old_code=input_code(input); /* Read in the first code, initialize the */
character=old_code; /* character variable, and send the first */
putc(old_code,output); /* code to the output file */
/*
** This is the main expansion loop. It reads in characters from the LZW file
** until it sees the special code used to inidicate the end of the data.
*/
while ((new_code=input_code(input)) != (MAX_VALUE))
{
if (++counter==1000) /* This section of code prints out */
{ /* an asterisk every 1000 characters */
counter=0; /* It is just a pacifier. */
printf("*");
}
/*
** This code checks for the special STRING+CHARACTER+STRING+CHARACTER+STRING
** case which generates an undefined code. It handles it by decoding
** the last code, and adding a single character to the end of the decode string.
*/
if (new_code>=next_code)
{
*decode_stack=character;
string=decode_string(decode_stack+1,old_code);
}
/*
** Otherwise we do a straight decode of the new code.
*/
else
string=decode_string(decode_stack,new_code);
/*
** Now we output the decoded string in reverse order.
*/
character=*string;
while (string >= decode_stack)
putc(*string--,output);
/*
** Finally, if possible, add a new code to the string table.
*/
if (next_code <= MAX_CODE)
{
prefix_code[next_code]=old_code;
append_character[next_code]=character;
next_code++;
}
old_code=new_code;
}
printf("\n");
}

/*
** This routine simply decodes a string from the string table, storing
** it in a buffer. The buffer can then be output in reverse order by
** the expansion program.
*/

unsigned char *decode_string(unsigned char *buffer,unsigned int code)
{
int i;

i=0;
while (code > 255)
{
*buffer++ = append_character[code];
code=prefix_code[code];
if (i++>=MAX_CODE)
{
printf("Fatal error during code expansion.\n");
exit(-3);
}
}
*buffer=code;
return(buffer);
}

/*
** The following two routines are used to output variable length
** codes. They are written strictly for clarity, and are not
** particularyl efficient.
*/

unsigned int input_code(FILE *input)
{
unsigned int return_value;
static int input_bit_count=0;
static unsigned long input_bit_buffer=0L;

while (input_bit_count <= 24)
{
input_bit_buffer |=
(unsigned long) getc(input) << (24-input_bit_count);
input_bit_count += 8;
}
return_value=input_bit_buffer >> (32-BITS);
input_bit_buffer <<= BITS;
input_bit_count -= BITS;
return(return_value);
}

void output_code(FILE *output,unsigned int code)
{
static int output_bit_count=0;
static unsigned long output_bit_buffer=0L;

output_bit_buffer |= (unsigned long) code << (32-BITS-output_bit_count);
output_bit_count += BITS;
while (output_bit_count >= 8)
{
putc(output_bit_buffer >> 24,output);
output_bit_buffer <<= 8;
output_bit_count -= 8;
}
}
[/code]
"A mente que se abre a uma nova idéia jamais volta ao seu tamanho original." (Albert Einstein).
Avatar do usuário
ivan
Word
 
Mensagens: 618
Registrado em: 12 Out 2006 21:27

Mensagempor barboza » 10 Nov 2009 05:23

Alesandro F Zagui escreveu:Você vai ter que criar o algoritmo pra isso na mão.

Como sua informacao vai de 0 a 51, você vai precisar de 6 bytes pra armazenar cada informação.

suponhamos o seguinte:

AAAAAA - BYTES DO PRIMEIRO VALOR
BBBBBB - BYTES DO SEGUNDO VALOR
CCCCCC- BYTES DO TERCEIRO VALOR
DDDDDD- BYTES DO QUARTO VALOR

Hoje provavelmente vc armazena assim:

endereco 1
00AAAAAA
endereço 2
00BBBBBB
endereço 3
00CCCCCC
endereço 4
00DDDDDD

Voce teria que criar um rotina que organizasse os bytes assim:

endereço 1
AAAAAABB
endereço 2
BBBBCCCC
endereço 3
CCDDDDDD


Antes precisa de 4 bytes e agora precisa de 3 pra armazenar a mesma informação.



Acho que vc quis dizer 6 bits.....
Os homens mentiriam muito menos se as mulheres fizessem menos perguntas.
Avatar do usuário
barboza
Word
 
Mensagens: 948
Registrado em: 17 Out 2006 13:42
Localização: Longe de onde gostaria de estar

Próximo

Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

x