Welcome! Log In Create A New Profile

Advanced

DIY Tiny OLED I2C full graphics controller

Posted by enif 
Re: DIY Tiny OLED I2C full graphics controller
June 14, 2015 01:41PM
Quote
Yellobello
no datasheet for the sainsmart display
No idea of sainsmart.. winking smiley

Quote
Yellobello
The connectors are called CS,RST,DC,SCLK,SDIN,GND and 3,3V..
I've a couple of 7pin SPIs named
GND, VCC, D0, D1, RST, DC, CS
plus some datasheets...
Due to them CS isn't used with 4wire SPI, CS should be connected to GND.
D0 is (S)CLK, it must be connected LCD4 / EXP1-Pin5 (RRD schematic)
D1 is (S)DTA / DI / SID, it must be connected to LCDE / Exp1-Pin3 (RRD schematic)
DC should be connected to LCDRS !! / Exp1-Pin4 (RRD schematic)
RST is Reset and should be connected to VCC due to RRD schematic.

I'm using that wiring together with ATMega8A projects only, mostly for displaying 3 large digits.
Not for Marlin/Repetier for I would need glasses + loupe + microscope..
All my OLEDs are running from SSD1306 / SH1106 and need different commands/inits compared to ST79.. ones.
But U8GLIB should handle it, SSD1306 SPI is listed.
Have a look at at the fast version, its runnin' fine on my pro micros.
Re: DIY Tiny OLED I2C full graphics controller
June 14, 2015 02:26PM
If your OLED can be reconfigured for I2C, then I still think that this is your best option. Why don't you post pictures of the front and the back of your OLED here - then may be we can find out how to activate the I2C mode...
Re: DIY Tiny OLED I2C full graphics controller
June 16, 2015 09:15AM
Yesterday evening I had some tries with my OLEDs. at the moment, I2C is the best option, indeed.
My first problem was an actual marlin copy, it didn't compile.
It seems that it has not much to do with Marlin from spring 2014 sad smiley((, my old I3 rework configuration.h sucks.
So I checked emotion tech / reprap France for a new version and found i3_rework 1.5.
This version is quite different to all other, too. But it compiles fine.
I2C is runnin' out of the box, only two declarations in configuration.h and dogm_lcd-implementation are needed.
With ISP I wasn't lucky, the Mega2560's "Standard" SPI Signals are not catched by RAMPS, they must be routed to other pins used by RAMPS.
For there exists a Reprap-Special-Version for the ST7920 named "ultralcd_st7920_u8glib_rrd.h" I guess we need a special version
for SSD1306-SPI-reprap too.

Edited 1 time(s). Last edit at 06/16/2015 09:16AM by bianchifan.
Re: DIY Tiny OLED I2C full graphics controller
June 17, 2015 03:18AM
FU** SPI !

I don´t want to bother with this stuff anymore.
Re-soldering the display´s resistors is also out of option since at least 4 of the smd resistors are packed in one resistor chip. I should have double checked when ordering it.. I thought that by counting the number of pins that the display is I2C and SPI in one. (still don´t know what the two non-SPI pins are used for)
I´ll use the display for an other project... still thanks for your help everyone. It´s just too much work.
I just invested another 10 euros and ordered I2C version of the display.
Re: DIY Tiny OLED I2C full graphics controller
June 17, 2015 03:47AM
@bianchifan:

Why don´t you use the current marlin version from Git?
In the 1.0.3 development branch, there´s even support for the 1309 I2C displays already implemented

Edited 1 time(s). Last edit at 06/17/2015 03:48AM by Yellobello.
Re: DIY Tiny OLED I2C full graphics controller
June 18, 2015 05:28AM
Quote
Yellobello
@bianchifan:

Why don´t you use the current marlin version from Git?

As I wrote above, it doesn't compile, totally different.
For using I must build a new config from scratch...I'm still happy with my old one.
SSD1306 and SSD1309 are different, I found only enif's stuff for 1306 I2C
Re: DIY Tiny OLED I2C full graphics controller
June 18, 2015 06:16AM
You should just be able to edit your values into the Configuration.h from 1.0.3 and be good to go . . . stuff has been added and reorganized, but none of the config parameters have changed since at least 1.0.0 (which is where I started . . . ).But no, you can't just drop the old Configuration.h file into 1.0.3 and have it work . . .

- Tim
Re: DIY Tiny OLED I2C full graphics controller
June 19, 2015 05:45AM
Oh sorry.. that was a typo.. I actually meant SSD1309
Re: DIY Tiny OLED I2C full graphics controller
June 20, 2015 03:49AM
I have just finished making the TinyOLED 1.4 for my briefcase 3D printer. Fantastic work Enif. An amazing effort in such a short space of time.

An added complication I had was that I was also trying to get a Max6675 thermocouple module working properly as well. I managed to get the thermocouple module almost working with a reprapdiscount graphics smart controller by loading up the latest development version of Marlin yesterday. The only negative symptom left was that the printer froze mid-print when I was printing from the SD card. I believe this is due to a conflict with both the thermocouple module and the SD card using the SPI. It prints reliably when I print from the computer i.e. without using the SD card.

I have two other observations on my new setup:

As Enif has noted earlier, the side facing encoder has an illogical response depending on if you are scrolling menus or changing numeric values. If you set the encoder rotation in firmware to suit the menus (rolling the thumbwheel downwards at the front to scroll downwards), then when you reach a screen where you change a numeric value the same downwards rotation increases the numeric value. I'm not quite sure how easy it is to code to make the numeric value decrease with downwards rotation.

It took a while to figure out how to get the system to boot up without getting a fatal Mintemp error on bootup. This problem is also probably related to my Max6675 thermocouple module but the problem went away when I put a microSD card into the slot! If I can't get the SD card and the Max6675 to play nicely together, I will be reverting to a thermister. I do like being able to print from the SD - especially when doing multi hour prints. There is history of Marlin developers working to resolve the SPI conflict but it seems to be one of those problems that hasn't yet been fully resolved.


My Prusa Mendel i2 inspired Repstrap with welded steel frame: [youtu.be]
And my Smartrap derived Briefcase 3D printer: [youtu.be]
Re: DIY Tiny OLED I2C full graphics controller
June 20, 2015 04:47AM
Quote
n.glasson

As Enif has noted earlier, the side facing encoder has an illogical response depending on if you are scrolling menus or changing numeric values. If you set the encoder rotation in firmware to suit the menus (rolling the thumbwheel downwards at the front to scroll downwards), then when you reach a screen where you change a numeric value the same downwards rotation increases the numeric value. I'm not quite sure how easy it is to code to make the numeric value decrease with downwards rotation.

Yes, I noticed that too already... Scrolling menus is allright but when changing numerical values, let´s say babysteps (where it is quite important to turn the knob in the proper direction in realtime, because the print is running) the change of value is illogical.
This has to be changed deep inside marlin.
If you can´t code, the best idea here would be to post an issue in the marlin git issues discussion.
Re: DIY Tiny OLED I2C full graphics controller
June 20, 2015 06:55AM
Quote
n.glasson
... The only negative symptom left was that the printer froze mid-print when I was printing from the SD card. I believe this is due to a conflict with both the thermocouple module and the SD card using the SPI. It prints reliably when I print from the computer i.e. without using the SD card.
...

This could be due to the wires going to the SD card reader / SPI thermocouple picking up electrical noise from the stepper motors during a print, hence corrupting the data from the SD card / SPI thermocouple. Our RepRap 3D printers generate plenty of electrical noise and the flat cables used to connect the LCD display are not insulated and pick up that noise acting like antennas. I have heard (but have not tried it myself) that simply wrapping the flat cable with aluminum foil decreases the noise pickup to manageable levels, or you may want to use properly shielded network cable with 8 conductors (and solder the shield to ground).
Re: DIY Tiny OLED I2C full graphics controller
June 21, 2015 10:03PM
I doubt that it is an electrical noise issue as I have been using the machine without this problem for a few months with a reprapdiscount graphics smart controller attached. Connecting the MAX6675 introduced the problem and that has a very short ribbon cable. The machine behaves fine if I print from a computer. It is more likely a conflict between the SD and MAX6675 on the SPI. I understand that the marlin implementation of the MAX6675 is far from bullet proof.

That said, I can't see any harm in using shielded cables, although I'll find a 12 core cable to connect the OLED controller and make it as short as I can. If the problem goes away with no other changes I'll let you know.


My Prusa Mendel i2 inspired Repstrap with welded steel frame: [youtu.be]
And my Smartrap derived Briefcase 3D printer: [youtu.be]
Re: DIY Tiny OLED I2C full graphics controller
July 01, 2015 07:50PM
More progress on the SD card issues I was having. Without the thermocouple module connected (using the original thermister for the hot end), I found that I was still getting weird behaviour when printing from the micro SD card on the Tiny OLED display controller. Symptoms were occasionally the X or Y axes would travel to zero and back again. The print would get very messy because the nozzle would dribble during the slow travels to zero and back. Even the extruder appeared to zero itself occasionally. I tried a different SD card reader and a different SD card and finally I connected the SD card reader via a sheilded cable. The shielded data cable made the problem go away. I tied the sheild to ground at both ends.

I haven't put the SD card reader back into the TinyOLED display case, preferring instead to mount it separately. The power supply for the SD reader now comes from Aux 3 on RAMPS rather than the I2C port as it was with the TinyOLED PCB. So I can't say if the problem was solved by only shielding the SD wiring, or by separating the power connection for the SD card (or a combination of both). I also don't really care what fixed it - I'm just happy that it now works reliably. My next move might be to bugger it up by adding in the thermocouple module again!

Edited 2 time(s). Last edit at 07/01/2015 08:41PM by n.glasson.


My Prusa Mendel i2 inspired Repstrap with welded steel frame: [youtu.be]
And my Smartrap derived Briefcase 3D printer: [youtu.be]
Re: DIY Tiny OLED I2C full graphics controller
July 02, 2015 02:21AM
Quote
n.glasson
...
As Enif has noted earlier, the side facing encoder has an illogical response depending on if you are scrolling menus or changing numeric values. If you set the encoder rotation in firmware to suit the menus (rolling the thumbwheel downwards at the front to scroll downwards), then when you reach a screen where you change a numeric value the same downwards rotation increases the numeric value. I'm not quite sure how easy it is to code to make the numeric value decrease with downwards rotation.
...

I have solved this issue in file ultralcd.cpp by adding after line 330 the additional line "encoderPosition = (unsigned)(-(int)encoderPosition);" as shown in the following patch:
*** ultralcd.cpp.ori    2015-05-08 18:47:27.000000000 +0200
--- ultralcd.cpp        2015-05-08 18:47:31.000000000 +0200
*************** static void lcd_status_screen() {
*** 328,333 ****
--- 328,335 ----
  
      #ifdef ULTIPANEL_FEEDMULTIPLY
        // Dead zone at 100% feedrate
+     encoderPosition = (unsigned)(-(int)encoderPosition);
+ 
        if ((feedrate_multiplier < 100 && (feedrate_multiplier + int(encoderPosition)) > 100) ||
                (feedrate_multiplier > 100 && (feedrate_multiplier + int(encoderPosition)) < 100)) {
          encoderPosition = 0;

Edited 1 time(s). Last edit at 07/02/2015 02:47AM by enif.
Re: DIY Tiny OLED I2C full graphics controller
July 03, 2015 02:39AM
Thanks for that Enif. A few minutes effort using your instructions and I now have it working perfectly. I'd imagine that a more elegant coding could be applied that limits the edits to the main config files in Marlin but I suppose that involves getting properly involved with collaboration in Marlin development. I manage to maintain some control over my meager efforts at editing firmware by adding my initials in a comment at every place where I edit anything. That way, whenever I move to the next version, I can do a search on all files for my initials and find everything that needs to be edited on the new version.

You will have read that I have separated the SD card reader and connected it with a shielded cable to resolve an interference issue. The SD reader is now mounted on this: http://www.thingiverse.com/thing:908319

I'm really stoked with the Tiny OLED display controller. It fits much better into my briefcase 3D printer than the larger alternatives. Thanks heaps.


My Prusa Mendel i2 inspired Repstrap with welded steel frame: [youtu.be]
And my Smartrap derived Briefcase 3D printer: [youtu.be]
Re: DIY Tiny OLED I2C full graphics controller
July 03, 2015 06:34PM
It looks like the fix for the rotary encoder isn't quite 100% yet. I still find it works the wrong way in some places. For example when I am printing I can turn the speed up by twisting the knob upwards (at the front) when I am on the info screen, but when I select speed from the tune menu the knob needs to be twisted down to increase the speed. I'm sure the programming can be properly sorted to make the side facing knob work logically. Regrettably I'm unable to contribute much to the search for a solution. I still love the Tiny OLED controller and will be making another one for my other machine - but until this issue is fixed, I'll probably revert to the previous coding so that at least the places where numeric adjustment occurs are consistent (if counter intuitive).


My Prusa Mendel i2 inspired Repstrap with welded steel frame: [youtu.be]
And my Smartrap derived Briefcase 3D printer: [youtu.be]
Re: DIY Tiny OLED I2C full graphics controller
July 04, 2015 06:10AM
Quote
n.glasson
It looks like the fix for the rotary encoder isn't quite 100% yet. I still find it works the wrong way in some places. For example when I am printing I can turn the speed up by twisting the knob upwards (at the front) when I am on the info screen, but when I select speed from the tune menu the knob needs to be twisted down to increase the speed...

Yes, you are right indeed! As I use my TinyOled just for checking the temperatures and adjusting the feed rate, I did not notice the problem with the value editing.. sad smiley

So here is a new attempt. It's again just a patch for ultralcd.cpp, but this time you need to add the line "#define SIDE_ENCODER" to your Configuration.h to activate these changes.

If SIDE_ENCODER is defined, it will reverse the direction of rotation of the encoder in general (which should affect all the encoder operations) and then explicitly revert (back) the menu rotation, because that should be left as it is in the front encoder (i.e. left -> down, right -> up).

--- ultralcd.cpp.ori103 2015-05-08 18:47:27.000000000 +0200
+++ ultralcd.cpp        2015-07-04 11:18:42.000000000 +0200
@@ -127,10 +127,18 @@
   /**
    * START_MENU generates the init code for a menu function
    */
+
+  // reverse menu direction for encoders mounted on the side
+  #ifdef SIDE_ENCODER
+    #define MENU_DIR -1
+  #else
+    #define MENU_DIR 1
+  #endif
+
   #define START_MENU() do { \
     encoderRateMultiplierEnabled = false; \
-    if (encoderPosition > 0x8000) encoderPosition = 0; \
-    uint8_t encoderLine = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM; \
+    if (MENU_DIR*encoderPosition < 0) encoderPosition = 0; \
+    uint8_t encoderLine = MENU_DIR*encoderPosition / ENCODER_STEPS_PER_MENU_ITEM; \
     if (encoderLine < currentMenuViewOffset) currentMenuViewOffset = encoderLine; \
     uint8_t _lineNr = currentMenuViewOffset, _menuItemNr; \
     bool wasClicked = LCD_CLICKED, itemSelected; \
@@ -204,7 +212,7 @@
     #define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(type, label, args...) MENU_ITEM(setting_edit_callback_ ## type, label, PSTR(label), ## args)
   #endif //!ENCODER_RATE_MULTIPLIER
   #define END_MENU() \
-      if (encoderLine >= _menuItemNr) { encoderPosition = _menuItemNr * ENCODER_STEPS_PER_MENU_ITEM - 1; encoderLine = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM; }\
+      if (encoderLine >= _menuItemNr) { encoderPosition = MENU_DIR*(_menuItemNr * ENCODER_STEPS_PER_MENU_ITEM - 1); encoderLine = _menuItemNr-1; }\
       if (encoderLine >= currentMenuViewOffset + LCD_HEIGHT) { currentMenuViewOffset = encoderLine - LCD_HEIGHT + 1; lcdDrawUpdate = 1; _lineNr = currentMenuViewOffset - 1; _drawLineNr = -1; } \
       } } while(0)
 
@@ -220,7 +228,7 @@
   uint8_t currentMenuViewOffset;              /* scroll offset in the current menu */
   millis_t next_button_update_ms;
   uint8_t lastEncoderBits;
-  uint32_t encoderPosition;
+  int32_t encoderPosition;
   #if (SDCARDDETECT > 0)
     bool lcd_oldcardstatus;
   #endif
@@ -1510,8 +1518,13 @@
 
   //manage encoder rotation
   uint8_t enc=0;
-  if (buttons & EN_A) enc |= B01;
-  if (buttons & EN_cool smiley enc |= B10;
+  #ifndef SIDE_ENCODER
+    if (buttons & EN_A ) enc |= B01;
+    if (buttons & EN_B ) enc |= B10;
+  #else // for side encoders reverse rotation direction
+    if (buttons & EN_B ) enc |= B01;
+    if (buttons & EN_A ) enc |= B10;
+  #endif
   if (enc != lastEncoderBits) {
     switch(enc) {
       case encrot0:

I have done some quick tests on my systems here, and so far it seems to work. But as I only use the very basic stuff here, more testing is certainly needed.

PS: Note that I changed the type of encoderPosition from uint32_t to int32_t. This seems to be the more natural type for this variable, and there are many int() casts that could be removed as well, in case someone someday decides to integrate this patch to a Marlin source tree. However, if someone sees a problem with this type change, or knows a good reason why encoderPosition needs to be unsigned, please let me know.
Re: DIY Tiny OLED I2C full graphics controller
July 04, 2015 05:51PM
Thanks enif - all seems to be working fine now. Much appreciated.


My Prusa Mendel i2 inspired Repstrap with welded steel frame: [youtu.be]
And my Smartrap derived Briefcase 3D printer: [youtu.be]
Re: DIY Tiny OLED I2C full graphics controller
August 07, 2015 02:57AM
we have produce some tiny oled and can be easy used on ramps1.4.

can be found at here

the example firmware can be found at here

Edited 1 time(s). Last edit at 08/07/2015 03:04AM by flyway97.
Re: DIY Tiny OLED I2C full graphics controller
August 19, 2015 04:47PM
Does someone run it on Melzi board?
I follow all instructions and oled works but encoder not.
In theory Melzi is compatible with Sanguinololu but in Melzi ADC inputs are on pins 36,35,34 and 33.
So i changed this part of code in pins_SANGUINOLOLU_11.h
#if  defined(SSD1306_OLED_I2C_CONTROLLER) || defined(SH1106_OLED_I2C_CONTROLLER)
      #define LCD_SDSS -1
      #define BTN_EN1 36  // A1 - rotary encoder A 
      #define BTN_EN2 35  // A2 - rotary encoder B
      #define BTN_ENC 34  // A3 - rotary encoder push switch
      //#define BEEPER  10  // I dont need beeper
   #endif
Did I miss some part of code to change?
Re: DIY Tiny OLED I2C full graphics controller
August 20, 2015 09:45AM
Are you sure that 34, 35, 36 really correspond to A3,A2,A1? Somehow that look to me not like the Arduino digital pin numbers, but like the pin numbers of the ATmega1284 DIP package...

Not sure, but I would rather have expected pin numbers something like 29,28,27 - but I can't check it right now...

Edited 1 time(s). Last edit at 08/20/2015 10:05AM by enif.
Re: DIY Tiny OLED I2C full graphics controller
August 20, 2015 02:09PM
In Melzi ATmega1284p is in TQFP package. I check pins with atmega datasheet, melzi documentation and with multimeter and its correct.
Pin 29 is Aref
Pin 28 is Gnd
Pin 27 is Vcc
Re: DIY Tiny OLED I2C full graphics controller
August 20, 2015 02:20PM
We don't need physical package pin numbers in the pins_SANGUINOLOLU_11.h. What we need are the Arduino digital output pins numbers (Dxx) which correspond to the A1/A2/A3 analog pins. Usually they occupy the numbers just above the "normal" digital output pins. According to the wiki these are A1->D30, A2->D29 and A3->D28.
Re: DIY Tiny OLED I2C full graphics controller
September 01, 2015 01:15PM
Connector Borad for TinyoLED
www.hkmakers.hk





Edited 4 time(s). Last edit at 09/01/2015 01:24PM by fredchan.
Attachments:
open | download - IMG-20150707-WA0008.jpg (174 KB)
open | download - IMG-20150707-WA0007.jpg (137.8 KB)
open | download - 1507082204415e11206d65dabd.jpg (32.7 KB)
Re: DIY Tiny OLED I2C full graphics controller
September 04, 2015 03:46PM
Quote
fredchan
Connector Borad for TinyoLED
www.hkmakers.hk
Wow $40 for a piece of bare PCB? Sure you didn't accidentialky add a zero in there? I would had bought one at $4.
Cheers.

Edited 1 time(s). Last edit at 09/04/2015 03:48PM by dintid.
Re: DIY Tiny OLED I2C full graphics controller
September 05, 2015 11:06AM
Quote
dintid
Quote
fredchan
Connector Borad for TinyoLED
www.hkmakers.hk
Wow $40 for a piece of bare PCB? Sure you didn't accidentialky add a zero in there? I would had bought one at $4.
Cheers.

That's $40 Hong Kong equivalent to just over $5 US I think
Re: DIY Tiny OLED I2C full graphics controller
September 06, 2015 12:54AM
Quote
dougal1957
Quote
dintid
Quote
fredchan
Connector Borad for TinyoLED
www.hkmakers.hk
Wow $40 for a piece of bare PCB? Sure you didn't accidentialky add a zero in there? I would had bought one at $4.
Cheers.

That's $40 Hong Kong equivalent to just over $5 US I think
Doh, thanks - rather embarrased. That's what reading on tablet gets me (small letters). Or just being too busy..
Can even change currency in upper right corner -> translates to $5.16 (ex tax etc)

Edited 6 time(s). Last edit at 09/06/2015 10:03AM by dintid.
Re: DIY Tiny OLED I2C full graphics controller
September 24, 2015 11:58AM
Quote
enif
This describes a little DIY project I did for building a I2C based tiny full graphic controller using the SSD1306 128x64 OLED display.

This OLED display comes in two sizes, 0.96" and 1.3", and can be ordered on eBay for a few dollars. So far I only have the 0.96" version, but I have now ordered the 1.3" version. Fortunately, the SSD1306 interface is already supported in U8GLIB, so no programming is needed, just some configuation changes. Since the OLED display uses the I2C, only 4 wires (VCC, GND, SCL, SDA) are needed for the display itself. Add to that the 3 signals for the rotary encoder plus one signal for an (optional!) piezo buzzer, to a total need for only 8 wires. I found this especially useful for the Sanguinololu, where not so many additional pins are available.

Other advantages of the OLED display are that is really bright, does not need any fiddling with the contrast, only draws a total current of about 8mA and, last but not least, works with either 5V or 3.3V supply and signals - the latter being particularly interesting for ARM based controller boards.

For building the controller you need the following:
  • an SSD1306 I2C 128x64 OLED display (available as 0.96" or 1.3" versions)
  • a rotary encoder with integrated click switch
  • a piezo buzzer (optional, just for audible feedback of click)
  • a piece of prototype PCB board (about 1.5"x2.5" is enough)
  • some wires and pin headers

Here first the schematic how I wired the components and connected them to either RAMPS or Sanguinololu..

The modifications to Marlin are only minimal changes in the files Configuration.h, Conditionals.h, dogm_lcd_implementation.h, pins_SANGUINOLOLU_11.h and pins_RAMPS_13.h. The attached patch file contains all the changes needed to the current version 1.0.3 of Marlin.

For those wanting printing from an SD-card (I don't), it is easy to add one of these cheap SPI based micro-SD modules that can be ordered on eBay for less than 2$, since the standards SPI pins used for the SD-cards are left untouched by the OLED display. Here pictures of my test using the tiny OLED controller together with an micro-SDcard module, on both RAMPS and Sanguinololu:
I know, buying a ready made 2004 or full graphic LCD controller is so cheap today, that you won't save any money by building things yourself. But that was not my aim for this project, rather my goal was (other than the fact that I really like tinkering) to have something really small, need only a minimum of cabling, draws only little current and is also working on 3.3V...
Firstly: Very nice work man smiling smiley

Anyone got it to Work with the new Marlin firmware, where the "Conditionals.h" file no longer exists?
I got it to Work successfully with previous versions of Marlin, but I can't seem to get it to work with the new layout.. anyone had any luck at this?
Re: DIY Tiny OLED I2C full graphics controller
September 25, 2015 07:37AM
Quote
dintid
Anyone got it to Work with the new Marlin firmware, where the "Conditionals.h" file no longer exists?

Which version do you refer to, exactly?
Re: DIY Tiny OLED I2C full graphics controller
September 26, 2015 04:56AM
I have a problem with I2C Display.
My SD-menu is very slow like this: video
Sorry, only registered users may post in this forum.

Click here to login