|
|
View previous topic :: View next topic |
Author |
Message |
Arkaedus
Joined: 29 Apr 2015 Posts: 2
|
Problem with PWM to do all I want using HEX values in EEPROM |
Posted: Sat Jun 27, 2015 5:38 am |
|
|
Hello
First of all, sorry for my English, I am not an English speaker.
I don't know how to do that because i don't know how to work with hex numbers to do the PWMs.
I have four variables in hex on the EEPROM in my PIC18F8722 (I need 3 PWM, can I do it with that PIC??) For each day of the week I have four variables they on a programmer to turn on some lights for an aquarium fish LED lights.
I have those variables, that are written on the PIC EEPROM memory for everyday of the week with the help of the DS1302 dow:
config_hour_init[dow], config_minute_init[dow]
config_hour_end[dow], config:minute_end[dow]
The variables are in HEX and I use a ds1302 to see if the hour and minutes are the same or not that ds1302 to turn on or off the lights and I show the values on a LCD40x4.
Now i want to do two PWM changing the value of those according to the time.
For example I put in the init configuration 12:03 and in the end 13:05
I want that the PWMs changes his value on that time like this:
The two first are for day cycle, warm white LEDs and White LEDS and the time each pwm value change with the variables values.
The another is for night i want that the PWM raises or fall in 1 hour when day cycle is off.
I have the lights turning on or off at the init or end but i need PWM to do that light more brightness or down his brightness.
Sorry i know that is very complicated but i need to know how to do it, because i want to do my LED Light for my aquarium.
If someone can tell me how to do at least one PWM i want to try to do.
Thank to all, and thanks to read and help me |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Sat Jun 27, 2015 6:00 am |
|
|
First, unless you are storing the values into the EEPROM, as text, they _won't_ be 'hex'.
Understand that hex is just a way of representing a number, and the chip actually just stores the number in binary:
Code: |
int8 val;
val=123;
val=0x7B;
val=0b01111011;
|
All, put exactly the same number into 'val'. It doesn't hold 'hex', or decimal, just the number (which it stores in binary).
Then, 'yes of course' you can do code to behave as you describe. You'll need a timer interrupt, and to ramp the values actually fed to the PWM, from one value to another, based on time.
Yes, your chiup can do three distinct PWM's (actually five). Use the three ECCP outputs, so the code is the same for all three channels (your PIC has two normal PWM's, and three ECCP PWM's - it is simpler to use the three similar channels, than to use one or two of one type, and then the others of the other type.
This is called programming!. What you need to do, is approach the tasks one by one. First verify you can store and retrieve the numbers required. Then prove you can control the three PWM's and adjust the values as required. Then work out the maths of the ramping, and starting on one channel, and ramping much faster than really required verify you can do the smooth changes required. Then put it together.... |
|
|
Arkaedus
Joined: 29 Apr 2015 Posts: 2
|
|
Posted: Mon Jun 29, 2015 12:04 am |
|
|
I don't explain it correctly.
I go to post my code.
This is DS1302 driver:
Code: | //////////////////////////////////////////////////////////////////////////
//// DS1302.C ////
//// Driver for Real Time Clock ////
//// ////
//// rtc_init() Call after power up////
//// ////
//// rtc_set_datetime(day,mth,year,dow,hour,min) Set the date/time ////
//// ////
//// rtc_get_date(day,mth,year,dow) Get the date ////
//// ////
//// rtc_get_time(hr,min,sec) Get the time ////
//// ////
//// rtc_write_nvr(address,data) Write to NVR ////
//// ////
//// data = rtc_read_nvr(address) Read from NVR ////
//// ////
//// get_bcd(data) Convert data to BCD ////
//// ////
//// rm_bcd(data) Convert data to int ////
//// ////
//////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
//////////////////////////////////////////////////////////////////////////
#ifndef RTC_SCLK
#define RTC_SCLK PIN_E1
#define RTC_IO PIN_E0
#define RTC_RST PIN_E2
#endif
void write_ds1302_byte(BYTE cmd) {
BYTE i;
for(i=0;i<=7;++i) {
output_bit(RTC_IO, shift_right(&cmd,1,0) );
output_high(RTC_SCLK);
output_low(RTC_SCLK);
}
}
void write_ds1302(BYTE cmd, BYTE data) {
output_high(RTC_RST);
write_ds1302_byte(cmd);
write_ds1302_byte(data);
output_low(RTC_RST);
}
BYTE read_ds1302(BYTE cmd) {
BYTE i,data;
output_high(RTC_RST);
write_ds1302_byte(cmd);
input(RTC_IO);
delay_us(1);
for(i=0;i<=7;++i) {
shift_right(&data,1,input(RTC_IO));
output_high(RTC_SCLK);
delay_us(2);
output_low(RTC_SCLK);
delay_us(2);
}
output_low(RTC_RST);
return(data);
}
void rtc_init() {
BYTE x;
output_low(RTC_RST);
delay_us(2);
output_low(RTC_SCLK);
write_ds1302(0x8e,0);
write_ds1302(0x90,0xa4);
x=read_ds1302(0x81);
if((x & 0x80)!=0)
write_ds1302(0x80,0);
}
void rtc_set_datetime(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min) {
write_ds1302(0x86,day);
write_ds1302(0x88,mth);
write_ds1302(0x8c,year);
write_ds1302(0x8a,dow);
write_ds1302(0x84,hr);
write_ds1302(0x82,min);
write_ds1302(0x80,(0));
}
void rtc_get_date(BYTE& day, BYTE& mth, BYTE& year, BYTE& dow) {
day = read_ds1302(0x87);
mth = read_ds1302(0x89);
year = read_ds1302(0x8d);
dow = read_ds1302(0x8b);
}
void rtc_get_time(BYTE& hr, BYTE& min, BYTE& sec) {
hr = read_ds1302(0x85);
min = read_ds1302(0x83);
sec = read_ds1302(0x81);
}
void rtc_write_nvr(BYTE address, BYTE data) {
write_ds1302(address|0xc0,data);
}
BYTE rtc_read_nvr(BYTE address) {
return(read_ds1302(address|0xc1));
} |
I print the value of the time get in DS1307 in LCD using that function:
Code: | //-----------------------------------------------------------------------------
void lcd_print_2num_bcd_lcd1(int num_bcd)
{
lcd_putc1((num_bcd >> 4) + 0x30); //DECENAS
lcd_putc1((num_bcd & 0x0F) + 0x30); //UNIDADES
}
//----------------------------------------------------------------------------- |
I configure the turn on and turn off the lights with that code:
Code: | //PANTALLA DE CONFIGURACION
case 1:
switch (config_cursor_actual)
{
//CURSOR EN DIA DE LA SEMANA
case 0:
if (puls_up_fs && comprobar_datos_config())
{
if (++config_dia_actual == 8) config_dia_actual = 1;
}
if (puls_down_fs && comprobar_datos_config())
{
if (--config_dia_actual == 0) config_dia_actual = 7;
}
//-------------------------
break;
//CURSOR EN DECENAS HORA INICIO
case 1:
if (puls_up_fs)
{
inc_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_INC, 1);
}
if (puls_down_fs)
{
dec_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_DEC, 1);
}
//-------------------------
break;
//CURSOR EN UNIDADES HORA INICIO
case 2:
if (puls_up_fs)
{
inc_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_INC, 0);
}
if (puls_down_fs)
{
dec_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_DEC, 0);
}
//-------------------------
break;
//CURSOR EN DECENAS MINUTOS INICIO
case 3:
if (puls_up_fs){
if (inc_2bcd(&config_minuto_inicio[config_dia_actual],
LIMIT_MINS_INC, 1))
{
inc_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_INC, 0);
}
}
if (puls_down_fs){
if (dec_2bcd(&config_minuto_inicio[config_dia_actual],
LIMIT_MINS_DEC, 1))
{
dec_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_DEC, 0);
}
}
//-------------------------
break;
//CURSOR EN UNIDADES MINUTOS INICIO
case 4:
if (puls_up_fs){
if (inc_2bcd(&config_minuto_inicio[config_dia_actual],
LIMIT_MINS_INC, 0))
{
inc_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_INC, 0);
}
}
if (puls_down_fs){
if (dec_2bcd(&config_minuto_inicio[config_dia_actual],
LIMIT_MINS_DEC, 0))
{
dec_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_DEC, 0);
}
}
//-------------------------
break;
//CURSOR EN DECENAS HORA FIN
case 5:
if (puls_up_fs)
{
inc_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_INC, 1);
}
if (puls_down_fs)
{
dec_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_DEC, 1);
}
//-------------------------
break;
//CURSOR EN UNIDADES HORA FIN
case 6:
if (puls_up_fs)
{
inc_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_INC, 0);
}
if (puls_down_fs)
{
dec_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_DEC, 0);
}
//-------------------------
break;
//CURSOR EN DECENAS MINUTOS FIN
case 7:
if (puls_up_fs){
if (inc_2bcd(&config_minuto_fin[config_dia_actual],
LIMIT_MINS_INC, 1))
{
inc_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_INC, 0);
}
}
if (puls_down_fs){
if (dec_2bcd(&config_minuto_fin[config_dia_actual],
LIMIT_MINS_DEC, 1))
{
dec_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_DEC, 0);
}
}
//-------------------------
break;
//CURSOR EN UNIDADES MINUTOS FIN
case 8:
if (puls_up_fs){
if (inc_2bcd(&config_minuto_fin[config_dia_actual],
LIMIT_MINS_INC, 0))
{
inc_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_INC, 0);
}
}
if (puls_down_fs){
if (dec_2bcd(&config_minuto_fin[config_dia_actual],
LIMIT_MINS_DEC, 0))
{
dec_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_DEC, 0);
}
}
//-------------------------
break;
|
Where I define that at the first lines:
#define LIMIT_HORAS_INC 0x24
#define LIMIT_MINS_INC 0x60
#define LIMIT_HORAS_DEC 0x23
#define LIMIT_MINS_DEC 0x59
It is printed on a LCD screen with that code:
Code: | //PANTALLA DE CONFIGURACION
case 1:
//ENCABEZADO
lcd_gotoxy (1,1);
printf (lcd_putc1 "< PANTALLA PARA PROGRAMAR EL ENCENDIDO >");
//DIA
lcd_gotoxy(1,2);
printf(lcd_putc1,"Encender el ");
lcd_gotoxy(13,2);
lcd_print_nom_dia_sem(config_dia_actual);
lcd_gotoxy(16,2);
printf(lcd_putc1," de ");
//INICIO
lcd_gotoxy(20,2);
lcd_print_2num_bcd_lcd1(config_hora_inicio[config_dia_actual]);
lcd_gotoxy(22,2);
printf(lcd_putc1,":");
lcd_gotoxy(23,2);
lcd_print_2num_bcd_lcd1(config_minuto_inicio[config_dia_actual]);
lcd_gotoxy(25,2);
printf(lcd_putc1," a ");
//FIN
lcd_gotoxy(28,2);
lcd_print_2num_bcd_lcd1(config_hora_fin[config_dia_actual]);
lcd_gotoxy(30,2);
printf(lcd_putc1,":");
lcd_gotoxy(31,2);
lcd_print_2num_bcd_lcd1(config_minuto_fin[config_dia_actual]);
lcd_gotoxy(33,2);
printf(lcd_putc1," ");
break; |
I change the values using a cursor and the code to increase and decrease values is this:
Code: | //-----------------------------------------------------------------------------
short inc_2bcd(int* num_bcd, int bcd_limite = 0x9A, short digito = 0)
//Significado de los parametros:
// num_bcd: numero de 2 cifras en BCD que queremos incrementar
// bcd_limite: valor una vez incrementado el numero BCD que se considera que
// ha habido un desbordamiento, volviendo al valor 0. Los unicos
// valores no BCD aceptables son desde 0x9A hasta 0xA0 que
// equivalen a 100 BCD.
// digito: especifica si se ha de incrementar la cifra de las unidades(0)
// o la de las decenas (1)
//
//Devuelve 1 si desborda por el limite
{
switch (digito)
{
//Incrementar unidades
case 0:
*num_bcd +=1; //Unidades + 1
if ((*num_bcd & 0x0F) > 9) //Unidades > 9?
{
*num_bcd &= 0xF0; //Unidades = 0
*num_bcd += 0x10; //Decenas + 1
}
if (*num_bcd >= bcd_limite)//Desbordamiento?
{
*num_bcd = 0x00; //Numero BCD = 00
return 1; //Devolver desbordamiento
}
break;
//Incrementar decenas
case 1:
*num_bcd += 0x10; //Decenas + 1
if (*num_bcd >= bcd_limite)//Desbordamiento?
{
*num_bcd &= 0x0F; //Decenas = 0
return 1; //Devolver desbordamiento
}
break;
}
return 0;
}
//-----------------------------------------------------------------------------
short dec_2bcd(int* num_bcd, int bcd_limite = 0x99, short digito = 0)
//Significado de los parametros:
// num_bcd: numero de 2 cifras en BCD que queremos decrementar
// bcd_limite: valor que tomará el numero BCD si se ha llegado a numeros
// negativos (desbordamiento).
// digito: especifica si se ha de decrementar la cifra de las unidades(0)
// o la de las decenas (1)
//
//Devuelve 1 si desborda por debajo de 0
{
switch (digito)
{
//Decrementar unidades
case 0:
*num_bcd -= 1; //Unidades - 1
if (*num_bcd == 0xFF) //Desbordamiento?
{
*num_bcd = bcd_limite; //Numero BCD = limite
return 1; //Devolver desbordamiento
}
if ((*num_bcd & 0x0F) == 0x0F)//Desbordamiento de Unidades?
{ //Automaticamente -> Decenas - 1
*num_bcd &= 0xF9;//0b11111001;//Unidades = 9
}
break;
//Decrementar decenas
case 1:
*num_bcd -= 0x10; //Decenas - 1
if ((*num_bcd & 0xF0) == 0xF0)//Desbordamiento?
{
*num_bcd = (*num_bcd & 0x0F) | (bcd_limite & 0xF0); //Decenas = Decenas de limite
if (*num_bcd > bcd_limite){ //Al restaurar las decenas, el numBCD es > limite?
*num_bcd -= 0x10; //Decenas - 1
}
return 1; //Devolver desbordamiento
}
break;
}
return 0;
} |
And this is EEPROM code where i store the 4 values (2 for init (hour_init, min_init) and 2 for end(hour_end, min_end)):
Code: | //-----------------------------------------------------------------------------
short cargar_eeprom() //Devuelve 0 si todo correcto / 1 si ha ocurrido algun error
{
short temp_return;
int *array;
int i;
int checksum_calc, checksum_leido;
checksum_calc = 0x4A; //Valor de inicio de la suma de comprobación de errores.
for (i = 0; i < 4; i++){
switch(i)
{
case 0: array = &config_hora_inicio[0]; break;
case 1: array = &config_minuto_inicio[0]; break;
case 2: array = &config_hora_fin[0]; break;
case 3: array = &config_minuto_fin[0]; break;
}
for (temp = 0; temp < 7; temp++){
array[temp] = read_eeprom((i*7) + temp);
if (array[temp] > 0x59) temp_return = 1;
checksum_calc += array[temp];
}
}
//Comprobación de errores
checksum_leido = read_eeprom(0x1C /* =4*7 */);
if (checksum_calc != checksum_leido){
//Reset Data
for (temp = 0; temp < 7; temp++){
config_hora_inicio[temp] = config_minuto_inicio[temp] = 0x00;
config_hora_fin[temp] = config_minuto_fin[temp] = 0x00;
}
return 1;
}else return 0;
}
//-----------------------------------------------------------------------------
void guardar_eeprom()
{
int *array;
int i;
int checksum;
checksum = 0x4A; //Valor de inicio de la suma de comprobación de errores.
for (i = 0; i < 4; i++){
switch(i)
{
case 0: array = &config_hora_inicio[0]; break;
case 1: array = &config_minuto_inicio[0]; break;
case 2: array = &config_hora_fin[0]; break;
case 3: array = &config_minuto_fin[0]; break;
}
for (temp = 0; temp < 7; temp++){
write_eeprom((i*7) + temp, array[temp]);
checksum += array[temp];
}
}
write_eeprom((0x1C /* =4*7 */), checksum);
}
//-----------------------------------------------------------------------------; |
I never done a PWM code this is the first that you should know.
My idea was do PWM using decimal system doing the rest (but i don't know how to do PWM, if you can help me if you know another form to do it, I would be very grateful).
resthour = config_hora_fin - config_hora_inicio
and
restmin = config_minuto_fin - config_hora_inicio
because i want multiply hour by 3600 and minutes by 60 to get the seconds and use it to do the PWM code
seconds total = resthour*3600+restmin*60
Thaks to read that, and sorry, but I want to post the code to show how I am working. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|