Tuesday, October 22, 2024

LCD 20x4 con CH32V003

Últimamente se ha popularizado mucho este microcontrolador CH32V003 por ser quizá el mas barato del mercado, lo he estado probando bastante y la verdad es que cumple muy bien con el trabajo, me falta hacer pruebas de durabilidad a largo plazo, pero por ahora promete mucho.

Recientemente quise usarlo para unos proyectos previamente hechos con otros microcontroladores  y como es normal te vas encontrando con los problemas típicos de cambiar de micro, en este caso, el primero es que como es relativamente nuevo no hay mucha información y otro es que no hay muchas librerías portadas hacia su entorno.

Es por eso que quiero escribir sobre esta primera librería que he portado que es para usar una pantalla LCD 20x4 basada en basadas en el chip (HD44780) con una interfaz I2C, y que también sirve para una 16x2.

Como dato rápido, me basé en la librería LiquidCrystal_I2C de DFRobot que está originalmente hecha para el entorno de Arduino en C++, pero este micro se programa en C nativo desde su IDE MounRiver Community.

Vi que otros lo han portado pero nadie comparte el código, así que aquí quería compartirlo yo, ya que sirve para muchos proyectos.

Sin mas preámbulo pasemos al código, que se compone de librería C (LCDI2C.c), cabecera (LCDI2C.h), librería (I2C.c), cabecera (I2C.h) así como el archivo main que demuestra el uso de la misma.

Libreria LCDI2C.c

#include "LCDI2C.h"
#include "I2C.h"
#include 

  uint8_t _Addr;
  uint8_t _displayfunction;
  uint8_t _displaycontrol;
  uint8_t _displaymode;
  uint8_t _numlines;
  uint8_t _cols;
  uint8_t _rows;
  uint8_t _backlightval;


void lcd_write(uint8_t value) {
	send(value, Rs);
}


// When the display powers up, it is configured as follows:
//
// 1. Display clear
// 2. Function set:
//    DL = 1; 8-bit interface data
//    N = 0; 1-line display
//    F = 0; 5x8 dot character font
// 3. Display on/off control:
//    D = 0; Display off
//    C = 0; Cursor off
//    B = 0; Blinking off
// 4. Entry mode set:
//    I/D = 1; Increment by 1
//    S = 0; No shift
//
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
// can't assume that its in that state when a sketch starts (and the
// LiquidCrystal constructor is called).


/*
 * Funcion para inicializar la pantalla
 * primero se inicializa I2C, luego se mandan los comandos a la pantalla
 * parametros: 	lcd_Addr la dirección de la pantalla generalmente 0x27
 * 				lcd_cols numero de columnas de la panatalla
 * 				lcd_rows filas de la pantalla
 * */
void lcd_Init(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows){

	  _Addr = lcd_Addr;
	  _cols = lcd_cols;
	  _rows = lcd_rows;
	  _backlightval = LCD_NOBACKLIGHT;

	IIC_Init(100000,0x27); //Funciona con 50,000 con 80,000 y con 100,000

	_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
	lcd_Begin(lcd_cols, lcd_rows,1);

}



void lcd_Begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
	if (lines > 1) {
		_displayfunction |= LCD_2LINE;
	}
	_numlines = lines;

	// for some 1 line displays you can select a 10 pixel high font
	if ((dotsize != 0) && (lines == 1)) {
		_displayfunction |= LCD_5x10DOTS;
	}

	// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
	// according to datasheet, we need at least 40ms after power rises above 2.7V
	// before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
	//delay(50);
	Delay_Ms(50);

	// Now we pull both RS and R/W low to begin commands
	expanderWrite(_backlightval);	// reset expanderand turn backlight off (Bit 8 =1)
	//delay(1000);

	Delay_Ms(1000);

  	//put the LCD into 4 bit mode
	// this is according to the hitachi HD44780 datasheet
	// figure 24, pg 46

	  // we start in 8bit mode, try to set 4 bit mode
   write4bits(0x03 << 4);
   //delayMicroseconds(4500); // wait min 4.1ms
   Delay_Us(4500);

   // second try
   write4bits(0x03 << 4);
   //delayMicroseconds(4500); // wait min 4.1ms
   Delay_Us(4500);

   // third go!
   write4bits(0x03 << 4);
   //delayMicroseconds(150);
   Delay_Us(150);

   // finally, set to 4-bit interface
   write4bits(0x02 << 4);


	// set # lines, font size, etc.
	lcd_command(LCD_FUNCTIONSET | _displayfunction);

	// turn the display on with no cursor or blinking default
	_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
	lcd_display();

	// clear it off
	lcd_clear();

	// Initialize to default text direction (for roman languages)
	_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;

	// set the entry mode
	lcd_command(LCD_ENTRYMODESET | _displaymode);

	lcd_home();

}

/********** high level commands, for the user! */
void lcd_clear(){
	lcd_command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero
	Delay_Us(2000);  // this command takes a long time!
}

void lcd_home(){
	lcd_command(LCD_RETURNHOME);  // set cursor position to zero
	Delay_Us(2000);  // this command takes a long time!
}

void lcd_setCursor(uint8_t col, uint8_t row){
	int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
	if ( row > _numlines ) {
		row = _numlines-1;    // we count rows starting w/0
	}
	lcd_command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}

// Turn the display on/off (quickly)
void lcd_noDisplay() {
	_displaycontrol &= ~LCD_DISPLAYON;
	lcd_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void lcd_display() {
	_displaycontrol |= LCD_DISPLAYON;
	lcd_command(LCD_DISPLAYCONTROL | _displaycontrol);
}

// Turns the underline cursor on/off
void lcd_noCursor() {
	_displaycontrol &= ~LCD_CURSORON;
	lcd_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void lcd_cursor() {
	_displaycontrol |= LCD_CURSORON;
	lcd_command(LCD_DISPLAYCONTROL | _displaycontrol);
}

// Turn on and off the blinking cursor
void lcd_noBlink() {
	_displaycontrol &= ~LCD_BLINKON;
	lcd_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void lcd_blink() {
	_displaycontrol |= LCD_BLINKON;
	lcd_command(LCD_DISPLAYCONTROL | _displaycontrol);
}

// These commands scroll the display without changing the RAM
void lcd_scrollDisplayLeft(void) {
	lcd_command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
}
void lcd_scrollDisplayRight(void) {
	lcd_command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
}

// This is for text that flows Left to Right
void lcd_leftToRight(void) {
	_displaymode |= LCD_ENTRYLEFT;
	lcd_command(LCD_ENTRYMODESET | _displaymode);
}

// This is for text that flows Right to Left
void lcd_rightToLeft(void) {
	_displaymode &= ~LCD_ENTRYLEFT;
	lcd_command(LCD_ENTRYMODESET | _displaymode);
}

// This will 'right justify' text from the cursor
void lcd_autoscroll(void) {
	_displaymode |= LCD_ENTRYSHIFTINCREMENT;
	lcd_command(LCD_ENTRYMODESET | _displaymode);
}

// This will 'left justify' text from the cursor
void lcd_noAutoscroll(void) {
	_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
	lcd_command(LCD_ENTRYMODESET | _displaymode);
}

// Allows us to fill the first 8 CGRAM locations
// with custom characters
void lcd_createChar(uint8_t location, uint8_t charmap[]) {
	location &= 0x7; // we only have 8 locations 0-7
	lcd_command(LCD_SETCGRAMADDR | (location << 3));
	for (int i=0; i<8 0="" _backlightval="" _data="" a="" backlight="" be="" cambiar="" charmap="" clave="" cmds="" command="" commands="" data="" ddr="" de="" delay_us="" either="" en="" enable="" expanderwrite="" for="" funciones="" high="" highnib="" i2c_send_data="" i2c_start="" i2c_stop="" i="" int="" la="" las="" lcd_backlight="" lcd_command="" lcd_nobacklight="" lcd_write="" level="" libreria="" liquidcrystal="" low="" lownib="" mid="" mode="" must="" na="" off="" on="" optional="" or="" pulse="" pulseenable="" pushing="" send="" sending="" the="" turn="" uint8_t="" value="" void="" write4bits="" write="">450ns

	expanderWrite(_data & ~En);	// En low
	Delay_Us(50);		// commands need > 37us to settle
}


// Alias functions

void cursor_on(){
	lcd_cursor();
}

void cursor_off(){
	lcd_noCursor();
}

void blink_on(){
	lcd_blink();
}

void blink_off(){
	lcd_noBlink();
}

void load_custom_character(uint8_t char_num, uint8_t *rows){
		lcd_createChar(char_num, rows);
}

void setBacklight(uint8_t new_val){
	if(new_val){
		lcd_backlight();		// turn backlight on
	}else{
		lcd_noBacklight();		// turn backlight off
	}
}


void lcd_printstr(const char* str) {
    while (*str) {
        print(*str++); // Envía cada caracter como dato
    }
}

void print(uint8_t value)
{
  return lcd_write(value);
}

// unsupported API functions
void off(){}
void on(){}
void setDelay (int cmdDelay,int charDelay) {}
uint8_t status(){return 0;}
uint8_t keypad (){return 0;}
uint8_t init_bargraph(uint8_t graphtype){return 0;}
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len,  uint8_t pixel_col_end){}
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len,  uint8_t pixel_row_end){}
void setContrast(uint8_t new_val){}


En esta libreria solo destacar que la magia se hace en la funcion expanderWrite() que es la que llama a las funciones de la libreria I2C, que es lo basico para mandar comandos por este protocolo a la pantalla. 

También se agrega la función lcd_Init() porque en la libreria C++ original se inicializaba en un constructor por lo que se necesita esta para hacer ese trabajo.

LCDI2C.h


#ifndef USER_LCDI2C_H_
#define USER_LCDI2C_H_

#include 

// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80

// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00

// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00

// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00

// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00

// flags for backlight control
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00

#define En 0x04
#define Rw 0x02
#define Rs 0x01

//Funciones basicas
  void send(uint8_t, uint8_t);
  void write4bits(uint8_t);
  void expanderWrite(uint8_t);
  void pulseEnable(uint8_t);

//Funciones del LCD
  void lcd_clear();
  void lcd_home();
  void lcd_noDisplay();
  void lcd_display();
  void lcd_noBlink();
  void lcd_blink();
  void lcd_noCursor();
  void lcd_cursor();
  void lcd_scrollDisplayLeft();
  void lcd_scrollDisplayRight();
  void lcd_printLeft();
  void lcd_printRight();
  void lcd_leftToRight();
  void lcd_rightToLeft();
  void lcd_shiftIncrement();
  void lcd_shiftDecrement();
  void lcd_noBacklight();
  void lcd_backlight();
  void lcd_autoscroll();
  void lcd_noAutoscroll();
  void lcd_createChar(uint8_t, uint8_t[]);
  void lcd_setCursor(uint8_t, uint8_t);
  void lcd_write(uint8_t);
  void lcd_command(uint8_t);

void lcd_Init(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows);
void lcd_Begin(uint8_t cols, uint8_t lines, uint8_t dotsize);

////compatibility API function aliases
void blink_on();						// alias for blink()
void blink_off();       					// alias for noBlink()
void cursor_on();      	 					// alias for cursor()
void cursor_off();      					// alias for noCursor()
void setBacklight(uint8_t new_val);				// alias for backlight() and nobacklight()
void load_custom_character(uint8_t char_num, uint8_t *rows);	// alias for createChar()
void lcd_printstr(const char* str);
void print(uint8_t value);

////Unsupported API functions (not implemented in this library)
uint8_t status();
void setContrast(uint8_t new_val);
uint8_t keypad();
void setDelay(int,int);
void on();
void off();
uint8_t init_bargraph(uint8_t graphtype);
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len,  uint8_t pixel_col_end);
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len,  uint8_t pixel_col_end);


#endif /* USER_LCDI2C_H_ */

 

Libreria I2C.c


#include "I2C.h"

void IIC_Init(u32 bound, u16 address)
{
    GPIO_InitTypeDef GPIO_InitStructure={0};
    I2C_InitTypeDef I2C_InitTSturcture={0};

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE );
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOC, &GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOC, &GPIO_InitStructure );

    I2C_InitTSturcture.I2C_ClockSpeed = bound;
    I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;
    I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitTSturcture.I2C_OwnAddress1 = address;
    I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;
    I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init( I2C1, &I2C_InitTSturcture );

    I2C_Cmd( I2C1, ENABLE );

}


void I2C_Start(u16 WriteAddr){
    while( I2C_GetFlagStatus( I2C1, I2C_FLAG_BUSY ) != RESET );
    I2C_GenerateSTART( I2C1, ENABLE );

    while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT ) );
    I2C_Send7bitAddress( I2C1, (WriteAddr<<1), I2C_Direction_Transmitter );
    while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );
    }
    
void I2C_Send_Data( u8 DataToWrite){
    if( I2C_GetFlagStatus( I2C1, I2C_FLAG_TXE ) !=  RESET )  {
    I2C_SendData( I2C1, DataToWrite );
    	}
    }
    
void I2C_Stop(){
    while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
    I2C_GenerateSTOP( I2C1, ENABLE );
    }
    

Esta libreria está basada en el ejemplo de mounriver I2C_7bit_mode para esta familia de microcontroladores,  de hecho es quiza mas esta la clave que la de LCD porque es la encargada de configurar e inicializar el periferico I2C.

I2C.h


#ifndef USER_I2C_H_
#define USER_I2C_H_
#include "debug.h"

void IIC_Init(u32 bound, u16 address);
void I2C_Start(u16 WriteAddr);
void I2C_Send_Data( u8 DataToWrite);
void I2C_Stop();

#endif /* USER_I2C_H_ */

 

Codigo principal main.c


/*
Proyecto para demostrar uso de libreria LCD I2C para pantallas 20x4
Conexiones: SCL--PC2
			SDA--PC1
*/

#include "debug.h"
#include "LCDI2C.h"


int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    SystemCoreClockUpdate();
    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n",SystemCoreClock);

    lcd_Init(0x27,20,4);
    lcd_backlight();
    lcd_clear();

    while(1)
    {
        lcd_setCursor(0,0);
        lcd_printstr("Hola mundo");
        for(int i=0;i<=19;i++){
        	lcd_scrollDisplayLeft();
        	Delay_Ms(200);
        }
        Delay_Ms(1000);

    }
}

Este codigo muestra el uso de la libreria, la inicialización de la pantalla y  algunas funciones mas como ejemplo.


 

Espero sea de utilidad esta libreria que a mi me llevo un tiempo de busqueda y luego de porteo, luego haré otro profunidizando en este microcontrolador y tambien adaptando algunas librerias para el propio entorno de Arduino.

Friday, June 19, 2015

Del IRC al Face

El tema surgio el otro dia a proposito de un post en un grupo de facebook al respecto del poco uso últimamente del IRC (Internet Relay Chat) y en general el chat, el chat como lo conocíamos antes (entrar en una página web o abrir tu cliente IRC favorito, seleccionar salas de conversación, ver la lista de gente desconocida al principio y comenzar luego a platicar) y les decía que parecen haber pasado de moda.

Todo tiene una explicación lógica, en este caso, considero que la proliferación de las redes sociales y en particular facebook es el causante, pero remontemonos un poco en lo que pasaba antes y en lo que ocurre ahora para tratar de descifrar por qué ocurrió lo que ocurrió.

En los tiempos del IRC la comunicación era totalmente impersonal, es decir, no veías a las personas a la cara, ni escuchabas su voz, así que lo primero que percibias era su manera de escribir, que en cierta forma era lo único que delataba su personalidad. Ahora bien, con la aparición de las redes no es que haya dejado de ser impersonal, las personas siguen estando cada una, detrás de un monitor (o pantalla táctil), sin embargo, ya no solo ves lo que escribe ya que de entrada, en la mayoría de redes debes contar con una imagen de perfil, una de fondo, etc. Lo cual obliga al usuario quiéralo o no a plasmar otro rasgo de su personalidad, le arrebata un poco de lo que le otorgaba el chat clásico, esa anonimidad ya no es total con estos perfiles.

Otro rasgo de las redes sociales es que, a diferencia del chat de antaño, los contactos son frecuentemente gente conocida, gente que en persona conocemos quiero decir, esa era una característica poco común del chat, esta característica definitivamente cambia la forma en que nos expresamos, mueve los límites de lo que decimos y compartimos.

El porqué se ha popularizado más una u otra, creo que es cuestión básicamente de dos factores:

Moda: Como las redes proliferaron con el boom del internet los nuevos usuarios llegaban a ver lo que había de nuevo, recordemos que el uso de internet en años anteriores no estaba tan extendido como hoy, tanto por el alcance del acceso a internet, como por la penetración de los moviles.

Afición a los gráficos: Es sabido de todos que las personas tenemos tendencia a seguir los medios que nos representan “menos trabajo”, las redes sociales son desde su nacimiento ricas en contenido gráfico y audiovisual, imágenes, videos, audio y decoraciones llamativas, el chat por su parte estaba lleno de texto, texto y texto, desde luego había chats con interfaz muy elaborada y colorida, pero el contenido no dejaba de ser el mismo, texto.

A pesar de todo, el IRC y el chat no han muerto, aún hay servidores IRC y páginas con chats, aunque cada vez menos, no han muerto, están solo adormilados, eso indica desde mi punto de vista que en realidad no van a morir, solo están esperando un aire de frescura, y seguramente resurgirán de sus cenizas en alguna nueva modalidad.

Monday, September 05, 2011

Joystick con java

En otro de mis proyectos, la primera parte, leer datos del
joystick esta desarrollado en Java usando la libreria
centralnexus,
el jlabel de swing, podemos decir que
estamos listos
para la siguiente.





Tuesday, December 15, 2009

Un nuevo proyecto

Pues se me ha ocurrido la idea de entrar en el mercado de forex, a ver que tal
me va, mientras tanto ya estoy estudiando todo el rollol, :D será mi nuevo
proyectin inconcluso por el momento.

Wednesday, September 30, 2009

Avance a la estacion de juegos

Ahora les traigo el avance de la estación de juego que documente
en una entrada anterior, le mande a hacer un cajoncito, de madera
y lo conecte a la PC y a jugar como en las arcadias.

Aqui una imagen:


Como se puede observar en la imagen -ademas de mis tenis apestosos
- el cajon cuenta con bisagra para poder hacer conexiones y dar
mantenimiento cuando algo falle.

Y otra:


Pero no se preocupen, queridos 20,000 lectores, este proyecto aun
sigue estando inconcluso pues falta el control secundario para echar retas.

RaY

Saturday, August 08, 2009

Too many open connections

Ese error del titulo aparecia una y otra y otra vez con mi aplicación hecha en struts + hibernate
me da un poco de verguenza aceptarlo pero me llevo como 6 meses repararlo - no me dedico diario a ella pero aun así es mucho tiempo - y ahora que lo resolví estoy algo euforico así que para
acordarme de este momento posteo la solución. Tal vez le ayude a alguien:

Lo primero que pense con ese error era que no estaba cerrando la sesion, dije claro por ahi
debe haber algun llamado a base donde olvide cerrarla, pero despues de revisar una por una,
varias veces ahi estaba session.close(); pues no era eso.

La segunda cosa en la que sospeche fue la base de datos (mysql) dije seguro tiene un bug
esa cosa, asi que hice pruebas, investigue y no solo me di cuenta de que no era sino que tambien
gracias a la respuesta de un participante en el bug tracking de mysql supe que no debia usar
el connection pooling nativo de hibernate para un ambiente productivo, asi que cambie a c3p0, pero tampoco era eso, el "too many open connections" seguia atormentandome despues de unas cuantas consultas.

Así que finalmente cuando todo estaba perdido era hora de leer el manual, a refinarme mas teoria de Hibernate, pues ahi estaba el pex, en realidad no sabia lo que estaba haciendo, eso pasa por aprender esta clase de cosas al vapor, muchas veces solo entiendes una embarrada, vamos al grano:

El problema.

Al abrir la sesion llamaba un metodo llamado abreConexion que al principio llamaba al siguiente codigo:

Configuration cfg = new Configuration(); cfg.setProperties(System.getProperties()); cfg.configure(); SessionFactory sessions = cfg.buildSessionFactory(); return sessions.openSession();

Pues claro, como ese codigo se ejecutaba con cada conexión, tenia una nueva fabrica de sessiones cada vez, y por consiguiente un pool de conexiones por cada fabriquita, así cada busqueda abria varias conexiones sin cerrarlas (pues estan en pool) hasta que me salia el mensajito del demonio.

La solucion.

Sencillo separar en una clase independiente la creacion de la fabriquita, con su respectivo metodo get para obtener la fabrica (la misma cada vez):

import org.hibernate.*;import org.hibernate.cfg.*;public class HibernateUtil { private static final SessionFactory sessionFactory; static { try { sessionFactory = new Configuration().configure().buildSessionFactory(); } catch (Throwable e) { System.err.println("Initial SessionFactory creation failed:" + e); throw new ExceptionInInitializerError(e); } } public static SessionFactory getSessionFactory() { return sessionFactory; }}

Lo demas es historia en mi metodo abreConexion solo llamo el metodo getSessionFactory y listo
adios problemas, ademas de que no aparece el error la aplicacion es mucho mas rapida pues la creación de la fabrica es muy lenta.


RaY... RTFM!!!

Monday, July 21, 2008

Siguiente

Por fin me dieron ganas de escribir de nuevo en este blog, que estoy
pensando seriamente en renombrar, creo que quedaría bien "El blog
de los proyectos inconclusos", en fin, en el capitulo anterior les
mostre mi bracito feo, que aun quiero terminar, pero no le he
dedicado tiempo, esta vez debido a mi recaida en las drogas
-si, debo aceptarlo- les presento mi nuevo proyecto inconcluso:


Así es, un tablero de arcadia, tal como lo jugaba en los locales de
videojuegos (o maquinitas), pues hace algún tiempo compre un
joystick tipo arcadia de alguna marca, este:


Pero definitivamente no era lo mismo, me dejaba una pequeña
insatisfacción, que se volvio frustración y luego casi odio cuando
uno de los micropulsadores que tiene se descompuso, entonces
uno de esos dias de vagancia por el país me encontre con una
tienda de refacciones de arcadias, una lagrima rodo por mi mejilla
y de inmediato compre la tabla, palancas, botones y pulsadores:


Solo faltaba la electrónica, así que tuve una idea que a la vez
serviría de venganza...



Y manos a la obra:





Después de unas cuantas horas de trabajo quedo lista para
usarse, ahora juego felizmente mis reliquias como street fighter II,
KOF97, y la no tan reliquia KOF2002, el joystick es compatible con
PS y PC lo que resta es hacer el segundo control y armar
un cajon para sujetar el tablero, así se ha convertido en uno mas
de mis proyectos inconclusos.

LCD 20x4 con CH32V003

Últimamente se ha popularizado mucho este microcontrolador CH32V003 por ser quizá el mas barato del mercado, lo he estado probando bastante ...