Components and supplies
SD Socket
Resistor 2.21k ohm
Single Turn Potentiometer- 10k ohms
Arduino UNO
RGB Backlight LCD - 16x2
Pushbutton switch 12mm
Resistor 1k ohm
Speaker: 0.25W, 8 ohms
Capacitor 22 µF
General Purpose Transistor NPN
General Purpose Transistor PNP
Resistor 47.5k ohm
Project description
Code
Talking Clock
c_cpp
1/* 2 * sd_bell.ino 3 * 4 * Created: 5/06/2017 23:34:47 5 * Author: moty22.co.uk 6 */ 7 8#include <LiquidCrystal.h> 9 10 // initialize the library with the numbers of the interface pins 11LiquidCrystal lcd(7, 8, A0, A1, A2, A3); 12 13const int CS = 10; // SD CS connected to digital pin PD4 14const int mosi = 11; 15const int clk = 13; 16const int ampON = 9; // led connected to digital pin PB0 17const int audio = 6; //output D6 18const int oc2b = 3; //1000Hz 19const int t1 = 5; //1000Hz 20const int talk = 2; //talk pushbutton 21const int minutes = A4; //minutes advance pushbutton 22const int hours = A5; //hours pushbutton 23int talkPB=1; // talk pushbutton status 24int minutesPB=1; // minutes pushbutton status 25int hoursPB=1; // hours pushbutton status 26 27unsigned long loc,BootSector, RootDir, SectorsPerFat, RootDirCluster, DataSector, FileCluster, FileSize; // 28unsigned int BytesPerSector, ReservedSectors, card; 29unsigned char fn=1, sdhc=0, SectorsPerCluster, Fats; 30unsigned char minute=0, hour=0; 31 32void setup() { 33 // put your setup code here, to run once: 34pinMode(CS, OUTPUT); 35pinMode(mosi, OUTPUT); 36pinMode(clk, OUTPUT); 37pinMode(ampON, OUTPUT); 38pinMode(talk, INPUT_PULLUP); 39pinMode(minutes, INPUT_PULLUP); 40pinMode(hours, INPUT_PULLUP); 41 42lcd.begin(16, 2); // set up the LCD's number of columns and rows: 43 44 //spi init 45SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR0) | _BV(SPR1); // Enable spi, Master, set clock rate fck/64 46SPSR = _BV(SPI2X); //set clock rate fck/64 = 250KHz 47 48 //PWM Timer0 49OCR0A = 0; 50TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00); //output in phase, fast PWM mode 51TCCR0B = _BV(CS00); // 16MHz/256 = 62.5KHz 52pinMode(audio, OUTPUT); 53 54 //1000 Hz - timer2 55OCR2A =249; 56OCR2B = 125; 57TCCR2A = _BV(COM2B1) | _BV(COM2B0) | _BV(WGM21) | _BV(WGM20); //output B in phase, fast PWM mode 58TCCR2B = _BV(WGM22) | _BV(CS22); // set prescaler to 64 and start the timer 59pinMode(oc2b, OUTPUT); 60 61 //60 sec - timer1 62// OCR1A = 0xEA5F; 63TCCR1A = _BV(WGM10) | _BV(WGM11) | _BV(COM1A0); // 64TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS11) | _BV(CS12); // input T1, PWM mode 65 66digitalWrite(CS, HIGH); 67//digitalWrite(ampON, LOW); 68 69 70 InitSD(); 71 if(sdhc){card = 1;}else{card=512;} //SD or SDHC 72 fat(); 73 if(BytesPerSector!=512){error();} 74 75} 76 77 78void loop() 79{ 80 81 talkPB=digitalRead(talk); 82 if(talkPB==LOW) 83 { 84 //read hours 85 if(hour < 21) {fn=hour; play();} 86 else if(hour == 20) {fn=20; play();} 87 else if(hour > 20) {fn=20; play(); fn=hour-20; play();} 88 fn=24; play(); //read "hours" 89 90 //read minutes 91 if(minute < 21) {fn=minute; play();} 92 else if(minute == 20) {fn=20; play();} 93 else if(minute > 20 && minute < 30) {fn=20; play(); fn=minute-20; play();} 94 else if(minute == 30) {fn=21; play();} 95 else if(minute > 30 && minute < 40) {fn=21; play(); fn=minute-30; play();} 96 else if(minute == 40) {fn=22; play();} 97 else if(minute > 40 && minute < 50) {fn=22; play(); fn=minute-40; play();} 98 else if(minute == 50) {fn=23; play();} 99 else if(minute > 50 && minute < 60) {fn=23; play(); fn=minute-50; play();} 100 fn=25; play(); //read "minutes" 101 fn=26; play(); //read message 102 OCR0A=0; //audio off 103 104 } 105 106 minutesPB=digitalRead(minutes); 107 if(minutesPB==LOW) 108 { 109 minute++; 110 if(minute>59) {minute=0;} 111 display(); 112 wait(); 113 } 114 115 hoursPB=digitalRead(hours); 116 if(hoursPB==LOW) 117 { 118 hour++; 119 if(hour>23) {hour=0;} 120 display(); 121 wait(); 122 } 123 124 if(TIFR1 & _BV(OCF1A)) //1 minute elapsed 125 { 126 OCR1A = 0xEA5F; //59999 counts = 1 minute 127 TIFR1 = _BV(OCF1A); //TMR1 interrupt reset 128 129 minute++; 130 if(minute>59) {minute=0; hour++;} 131 if(hour>23) hour=0; 132 display(); 133 134 } 135} 136 137 //find the file and play it 138 void play(void) 139 { 140 if(!sdhc){fn += 1;} //if not SDHC first file = 1 141 if(fn > 15) 142 { 143 fn -=16; file(fn*32+20,1); //32 bytes per file descriptor at offset of 20 144 } 145 else 146 { 147 file(fn*32+20,0); //32 bytes per file descriptor at offset of 20 148 } 149 loc=(1 + (DataSector) + (unsigned long)(FileCluster-2) * SectorsPerCluster) * card ; 150 ReadSD(); 151 } 152 153 //LCD update 154 void display(void) 155 { 156 lcd.setCursor(5, 0); // top left 157 if(hour<10)lcd.print(" "); 158 lcd.print(hour); 159 lcd.print(":"); 160 if(minute<10)lcd.print("0"); 161 lcd.print(minute); 162 } 163 164 //SD error display 165 void error(void) 166 { 167 lcd.setCursor(0, 1); // bottom left 168 lcd.print("SD ERROR"); 169 lcd.setCursor(0, 0); // top left 170 } 171 172 //1 sec delay 173 void wait(void) 174 { 175 unsigned long i; //,j 176 for(i=0;i<100000;i++) 177 { 178 digitalWrite(ampON, LOW); 179 } 180 } 181 182 void ReadSD(void) 183 { 184 unsigned int i,r; 185 unsigned char read_data; 186 digitalWrite(CS, LOW); 187 r = Command(18,loc,0xFF); //read multi-sector 188 if(r != 0) error(); //if command failed error(); 189 190 while(FileSize--) 191 { 192 while(spi(0xFF) != 0xFE); // wait for first byte 193 for(i=0;i<512;i++){ 194 // 3 rounds of timer 0 = total of time to get 22 khz 195 while (!(TIFR0 & _BV(OCF0A))){} 196 TIFR0 = _BV(OCF0A); //TMR0 interrupt reset 197 while (!(TIFR0 & _BV(OCF0A))){} 198 TIFR0 = _BV(OCF0A); //TMR0 interrupt reset 199 while (!(TIFR0 & _BV(OCF0A))){} 200 201 OCR0A=spi(0xFF); //write byte to PWM 202 TIFR0 = _BV(OCF0A); //TMR0 interrupt reset 203 } 204 spi(0xFF); //discard of CRC 205 spi(0xFF); 206 } 207 208 Command(12,0x00,0xFF); //stop transmit 209 spi(0xFF); 210 spi(0xFF); 211 digitalWrite(CS, HIGH); 212 spi(0xFF); 213 } 214 215void file(unsigned int offset, unsigned char sect) //find files 216{ 217 unsigned int r,i; 218 unsigned char fc[4], fs[4]; // 219 220 digitalWrite(CS, LOW); 221 r = Command(17,(RootDir+sect)*card,0xFF); //read boot-sector for info from file entry 222 if(r != 0) error(); //if command failed 223 224 while(spi(0xFF) != 0xFe); // wait for first byte 225 for(i=0;i<512;i++){ 226 if(i==offset){fc[2]=spi(0xFF);} 227 else if(i==offset+1){fc[3]=spi(0xFF);} 228 else if(i==offset+6){fc[0]=spi(0xFF);} 229 else if(i==offset+7){fc[1]=spi(0xFF);} 230 231 else if(i==offset+8){fs[0]=spi(0xFF);} 232 else if(i==offset+9){fs[1]=spi(0xFF);} 233 else if(i==offset+10){fs[2]=spi(0xFF);} 234 else if(i==offset+11){fs[3]=spi(0xFF);} 235 else{spi(0xFF);} 236 237 } 238 spi(0xFF); //discard of CRC 239 spi(0xFF); 240 digitalWrite(CS, HIGH); 241 spi(0xFF); 242 FileCluster = fc[0] | ( (unsigned long)fc[1] << 8 ) | ( (unsigned long)fc[2] << 16 ) | ( (unsigned long)fc[3] << 24 ); 243 FileSize = fs[0] | ( (unsigned long)fs[1] << 8 ) | ( (unsigned long)fs[2] << 16 ) | ( (unsigned long)fs[3] << 24 ); 244 FileSize = FileSize/512-1; //file size in sectors 245} 246 247void fat (void) 248{ 249 unsigned int r,i; 250 unsigned char pfs[4],bps1,bps2,rs1,rs2,spf[4],rdc[4]; //pfs=partition first sector ,de1,de2,spf1,d[7] 251 252 digitalWrite(CS, LOW); 253 r = Command(17,0,0xFF); //read MBR-sector 254 if(r != 0) error(); //if command failed 255 256 while(spi(0xFF) != 0xFe); // wait for first byte 257 for(i=0;i<512;i++){ 258 if(i==454){pfs[0]=spi(0xFF);} //pfs=partition first sector 259 else if(i==455){pfs[1]=spi(0xFF);} 260 else if(i==456){pfs[2]=spi(0xFF);} 261 else if(i==457){pfs[3]=spi(0xFF);} 262 else{spi(0xFF);} 263 264 } 265 spi(0xFF); //discard of CRC 266 spi(0xFF); 267 digitalWrite(CS, HIGH); 268 spi(0xFF); 269 //convert 4 bytes to long int 270 BootSector = pfs[0] | ( (unsigned long)pfs[1] << 8 ) | ( (unsigned long)pfs[2] << 16 ) | ( (unsigned long)pfs[3] << 24 ); 271 272 digitalWrite(CS, LOW); 273 r = Command(17,BootSector*card,0xFF); //read boot-sector 274 if(r != 0) error(); //if command failed 275 276 while(spi(0xFF) != 0xFe); // wait for first byte 277 for(i=0;i<512;i++){ 278 279 if(i==11){bps1=spi(0xFF);} //bytes per sector 280 else if(i==12){bps2=spi(0xFF);} 281 else if(i==13){SectorsPerCluster=spi(0xFF);} 282 else if(i==14){rs1=spi(0xFF);} 283 else if(i==15){rs2=spi(0xFF);} 284 else if(i==16){Fats=spi(0xFF);} //number of FATs 285 else if(i==36){spf[0]=spi(0xFF);} 286 else if(i==37){spf[1]=spi(0xFF);} 287 else if(i==38){spf[2]=spi(0xFF);} 288 else if(i==39){spf[3]=spi(0xFF);} 289 else if(i==44){rdc[0]=spi(0xFF);} 290 else if(i==45){rdc[1]=spi(0xFF);} 291 else if(i==46){rdc[2]=spi(0xFF);} 292 else if(i==47){rdc[3]=spi(0xFF);} 293 else{spi(0xFF);} 294 295 } 296 spi(0xFF); //discard of CRC 297 spi(0xFF); 298 digitalWrite(CS, HIGH); 299 spi(0xFF); 300 301 BytesPerSector = bps1 | ( (unsigned int)bps2 << 8 ); 302 ReservedSectors = rs1 | ( (unsigned int)rs2 << 8 ); //from partition start to first FAT 303 RootDirCluster = rdc[0] | ( (unsigned long)rdc[1] << 8 ) | ( (unsigned long)rdc[2] << 16 ) | ( (unsigned long)rdc[3] << 24 ); 304 SectorsPerFat = spf[0] | ( (unsigned long)spf[1] << 8 ) | ( (unsigned long)spf[2] << 16 ) | ( (unsigned long)spf[3] << 24 ); 305 DataSector = BootSector + (unsigned long)Fats * (unsigned long)SectorsPerFat + (unsigned long)ReservedSectors; // + 1 306 RootDir = (RootDirCluster -2) * (unsigned long)SectorsPerCluster + DataSector; 307} 308 309unsigned char spi(unsigned char data) // send character over spi 310{ 311 SPDR = data; // Start transmission 312 while(!(SPSR & _BV(SPIF))); // Wait for transmission to complete 313 return SPDR; // received byte 314 315} 316 //assemble a 32 bits command 317char Command(unsigned char frame1, unsigned long adrs, unsigned char frame2 ) 318{ 319 unsigned char i, res; 320 spi(0xFF); 321 spi((frame1 | 0x40) & 0x7F); //first 2 bits are 01 322 spi((adrs & 0xFF000000) >> 24); //first of the 4 bytes address 323 spi((adrs & 0x00FF0000) >> 16); 324 spi((adrs & 0x0000FF00) >> 8); 325 spi(adrs & 0x000000FF); 326 spi(frame2 | 1); //CRC and last bit 1 327 328 for(i=0;i<10;i++) // wait for received character 329 { 330 res = spi(0xFF); 331 if(res != 0xFF)break; 332 } 333 return res; 334} 335 336void InitSD(void) 337{ 338 unsigned char i,r[4]; 339 340 digitalWrite(CS, HIGH); 341 for(i=0; i < 10; i++)spi(0xFF); // min 74 clocks 342 digitalWrite(CS, LOW); // Enabled for spi mode 343 344 i=100; //try idle state for up to 100 times 345 while(Command(0x00,0,0x95) !=1 && i!=0) 346 { 347 digitalWrite(CS, HIGH); 348 spi(0xFF); 349 digitalWrite(CS, LOW); 350 i--; 351 } 352 if(i==0) error(); //idle failed 353 354 if (Command(8,0x01AA,0x87)==1){ //check card is 3.3V 355 r[0]=spi(0xFF); r[1]=spi(0xFF); r[2]=spi(0xFF); r[3]=spi(0xFF); //rest of R7 356 if ( r[2] == 0x01 && r[3] == 0xAA ){ //Vdd OK (3.3V) 357 358 //Command(59,0,0xFF); //CRC off 359 Command(55,0,0xFF); 360 while(Command(41,0x40000000,0xFF)){Command(55,0,0xFF);} //ACMD41 with HCS bit 361 } 362 }else{error();} 363 364 if (Command(58,0,0xFF)==0){ //read CCS in the OCR - SD or SDHC 365 r[0]=spi(0xFF); r[1]=spi(0xFF); r[2]=spi(0xFF); r[3]=spi(0xFF); //rest of R3 366 sdhc=r[0] & 0x40; 367 //if(r[0] & 0x40)sdLED=1; 368 } 369 SPCR &= ~(_BV(SPR1)); // set clock rate fck/8 = 2MHz 370 digitalWrite(CS, HIGH); 371} 372 373
Talking Clock
c_cpp
1/* 2 * sd_bell.ino 3 * 4 * Created: 5/06/2017 23:34:47 5 * Author: 6 moty22.co.uk 7 */ 8 9#include <LiquidCrystal.h> 10 11 // initialize 12 the library with the numbers of the interface pins 13LiquidCrystal lcd(7, 8, A0, 14 A1, A2, A3); 15 16const int CS = 10; // SD CS connected to digital pin 17 PD4 18const int mosi = 11; 19const int clk = 13; 20const int ampON = 9; // 21 led connected to digital pin PB0 22const int audio = 6; //output D6 23const 24 int oc2b = 3; //1000Hz 25const int t1 = 5; //1000Hz 26const int talk = 27 2; //talk pushbutton 28const int minutes = A4; //minutes advance pushbutton 29const 30 int hours = A5; //hours pushbutton 31int talkPB=1; // talk pushbutton 32 status 33int minutesPB=1; // minutes pushbutton status 34int hoursPB=1; 35 // hours pushbutton status 36 37unsigned long loc,BootSector, RootDir, 38 SectorsPerFat, RootDirCluster, DataSector, FileCluster, FileSize; // 39unsigned 40 int BytesPerSector, ReservedSectors, card; 41unsigned char fn=1, sdhc=0, SectorsPerCluster, 42 Fats; 43unsigned char minute=0, hour=0; 44 45void setup() { 46 // put your 47 setup code here, to run once: 48pinMode(CS, OUTPUT); 49pinMode(mosi, OUTPUT); 50pinMode(clk, 51 OUTPUT); 52pinMode(ampON, OUTPUT); 53pinMode(talk, INPUT_PULLUP); 54pinMode(minutes, 55 INPUT_PULLUP); 56pinMode(hours, INPUT_PULLUP); 57 58lcd.begin(16, 2); // set 59 up the LCD's number of columns and rows: 60 61 //spi init 62SPCR = _BV(SPE) 63 | _BV(MSTR) | _BV(SPR0) | _BV(SPR1); // Enable spi, Master, set clock rate fck/64 64SPSR 65 = _BV(SPI2X); //set clock rate fck/64 = 250KHz 66 67 //PWM Timer0 68OCR0A 69 = 0; 70TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00); //output in phase, fast 71 PWM mode 72TCCR0B = _BV(CS00); // 16MHz/256 = 62.5KHz 73pinMode(audio, OUTPUT); 74 75 76 //1000 Hz - timer2 77OCR2A =249; 78OCR2B = 125; 79TCCR2A = _BV(COM2B1) | 80 _BV(COM2B0) | _BV(WGM21) | _BV(WGM20); //output B in phase, fast PWM mode 81TCCR2B 82 = _BV(WGM22) | _BV(CS22); // set prescaler to 64 and start the timer 83pinMode(oc2b, 84 OUTPUT); 85 86 //60 sec - timer1 87// OCR1A = 0xEA5F; 88TCCR1A = _BV(WGM10) 89 | _BV(WGM11) | _BV(COM1A0); // 90TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS11) 91 | _BV(CS12); // input T1, PWM mode 92 93digitalWrite(CS, HIGH); 94//digitalWrite(ampON, 95 LOW); 96 97 98 InitSD(); 99 if(sdhc){card = 1;}else{card=512;} //SD or SDHC 100 101 fat(); 102 if(BytesPerSector!=512){error();} 103 104} 105 106 107void loop() 108{ 109 110 111 talkPB=digitalRead(talk); 112 if(talkPB==LOW) 113 { 114 //read 115 hours 116 if(hour < 21) {fn=hour; play();} 117 else if(hour == 20) 118 {fn=20; play();} 119 else if(hour > 20) {fn=20; play(); fn=hour-20; play();} 120 121 fn=24; play(); //read "hours" 122 123 //read minutes 124 125 if(minute < 21) {fn=minute; play();} 126 else if(minute == 20) {fn=20; 127 play();} 128 else if(minute > 20 && minute < 30) {fn=20; play(); fn=minute-20; 129 play();} 130 else if(minute == 30) {fn=21; play();} 131 else if(minute 132 > 30 && minute < 40) {fn=21; play(); fn=minute-30; play();} 133 else if(minute 134 == 40) {fn=22; play();} 135 else if(minute > 40 && minute < 50) {fn=22; play(); 136 fn=minute-40; play();} 137 else if(minute == 50) {fn=23; play();} 138 else 139 if(minute > 50 && minute < 60) {fn=23; play(); fn=minute-50; play();} 140 fn=25; 141 play(); //read "minutes" 142 fn=26; play(); //read message 143 OCR0A=0; 144 //audio off 145 146 } 147 148 minutesPB=digitalRead(minutes); 149 150 if(minutesPB==LOW) 151 { 152 minute++; 153 if(minute>59) {minute=0;} 154 155 display(); 156 wait(); 157 } 158 159 hoursPB=digitalRead(hours); 160 161 if(hoursPB==LOW) 162 { 163 hour++; 164 if(hour>23) {hour=0;} 165 166 display(); 167 wait(); 168 } 169 170 if(TIFR1 & _BV(OCF1A)) //1 171 minute elapsed 172 { 173 OCR1A = 0xEA5F; //59999 counts = 1 minute 174 175 TIFR1 = _BV(OCF1A); //TMR1 interrupt reset 176 177 minute++; 178 if(minute>59) 179 {minute=0; hour++;} 180 if(hour>23) hour=0; 181 display(); 182 183 } 184} 185 186 187 //find the file and play it 188 void play(void) 189 { 190 if(!sdhc){fn += 191 1;} //if not SDHC first file = 1 192 if(fn > 15) 193 { 194 fn -=16; 195 file(fn*32+20,1); //32 bytes per file descriptor at offset of 20 196 } 197 198 else 199 { 200 file(fn*32+20,0); //32 bytes per file descriptor at 201 offset of 20 202 } 203 loc=(1 + (DataSector) + (unsigned long)(FileCluster-2) 204 * SectorsPerCluster) * card ; 205 ReadSD(); 206 } 207 208 //LCD update 209 210 void display(void) 211 { 212 lcd.setCursor(5, 0); // top left 213 if(hour<10)lcd.print(" 214 "); 215 lcd.print(hour); 216 lcd.print(":"); 217 if(minute<10)lcd.print("0"); 218 219 lcd.print(minute); 220 } 221 222 //SD error display 223 void error(void) 224 225 { 226 lcd.setCursor(0, 1); // bottom left 227 lcd.print("SD ERROR"); 228 229 lcd.setCursor(0, 0); // top left 230 } 231 232 //1 sec delay 233 void 234 wait(void) 235 { 236 unsigned long i; //,j 237 for(i=0;i<100000;i++) 238 239 { 240 digitalWrite(ampON, LOW); 241 } 242 } 243 244 void ReadSD(void) 245 246 { 247 unsigned int i,r; 248 unsigned char read_data; 249 digitalWrite(CS, 250 LOW); 251 r = Command(18,loc,0xFF); //read multi-sector 252 if(r != 0) error(); 253 //if command failed error(); 254 255 while(FileSize--) 256 { 257 258 while(spi(0xFF) != 0xFE); // wait for first byte 259 for(i=0;i<512;i++){ 260 261 // 3 rounds of timer 0 = total of time to get 22 khz 262 while 263 (!(TIFR0 & _BV(OCF0A))){} 264 TIFR0 = _BV(OCF0A); //TMR0 interrupt reset 265 266 while (!(TIFR0 & _BV(OCF0A))){} 267 TIFR0 = _BV(OCF0A); //TMR0 268 interrupt reset 269 while (!(TIFR0 & _BV(OCF0A))){} 270 271 OCR0A=spi(0xFF); 272 //write byte to PWM 273 TIFR0 = _BV(OCF0A); //TMR0 interrupt reset 274 275 } 276 spi(0xFF); //discard of CRC 277 spi(0xFF); 278 } 279 280 281 Command(12,0x00,0xFF); //stop transmit 282 spi(0xFF); 283 spi(0xFF); 284 285 digitalWrite(CS, HIGH); 286 spi(0xFF); 287 } 288 289void file(unsigned int 290 offset, unsigned char sect) //find files 291{ 292 unsigned int r,i; 293 unsigned 294 char fc[4], fs[4]; // 295 296 digitalWrite(CS, LOW); 297 r = Command(17,(RootDir+sect)*card,0xFF); 298 //read boot-sector for info from file entry 299 if(r != 0) error(); //if 300 command failed 301 302 while(spi(0xFF) != 0xFe); // wait for first byte 303 for(i=0;i<512;i++){ 304 305 if(i==offset){fc[2]=spi(0xFF);} 306 else if(i==offset+1){fc[3]=spi(0xFF);} 307 308 else if(i==offset+6){fc[0]=spi(0xFF);} 309 else if(i==offset+7){fc[1]=spi(0xFF);} 310 311 312 else if(i==offset+8){fs[0]=spi(0xFF);} 313 else if(i==offset+9){fs[1]=spi(0xFF);} 314 315 else if(i==offset+10){fs[2]=spi(0xFF);} 316 else if(i==offset+11){fs[3]=spi(0xFF);} 317 318 else{spi(0xFF);} 319 320 } 321 spi(0xFF); //discard of CRC 322 spi(0xFF); 323 324 digitalWrite(CS, HIGH); 325 spi(0xFF); 326 FileCluster = fc[0] | ( (unsigned 327 long)fc[1] << 8 ) | ( (unsigned long)fc[2] << 16 ) | ( (unsigned long)fc[3] << 24 328 ); 329 FileSize = fs[0] | ( (unsigned long)fs[1] << 8 ) | ( (unsigned long)fs[2] 330 << 16 ) | ( (unsigned long)fs[3] << 24 ); 331 FileSize = FileSize/512-1; //file 332 size in sectors 333} 334 335void fat (void) 336{ 337 unsigned int r,i; 338 unsigned 339 char pfs[4],bps1,bps2,rs1,rs2,spf[4],rdc[4]; //pfs=partition first sector ,de1,de2,spf1,d[7] 340 341 342 digitalWrite(CS, LOW); 343 r = Command(17,0,0xFF); //read MBR-sector 344 345 if(r != 0) error(); //if command failed 346 347 while(spi(0xFF) != 0xFe); 348 // wait for first byte 349 for(i=0;i<512;i++){ 350 if(i==454){pfs[0]=spi(0xFF);} 351 //pfs=partition first sector 352 else if(i==455){pfs[1]=spi(0xFF);} 353 else 354 if(i==456){pfs[2]=spi(0xFF);} 355 else if(i==457){pfs[3]=spi(0xFF);} 356 else{spi(0xFF);} 357 358 359 } 360 spi(0xFF); //discard of CRC 361 spi(0xFF); 362 digitalWrite(CS, 363 HIGH); 364 spi(0xFF); 365 //convert 4 bytes to long int 366 BootSector = pfs[0] 367 | ( (unsigned long)pfs[1] << 8 ) | ( (unsigned long)pfs[2] << 16 ) | ( (unsigned 368 long)pfs[3] << 24 ); 369 370 digitalWrite(CS, LOW); 371 r = Command(17,BootSector*card,0xFF); 372 //read boot-sector 373 if(r != 0) error(); //if command failed 374 375 376 while(spi(0xFF) != 0xFe); // wait for first byte 377 for(i=0;i<512;i++){ 378 379 380 if(i==11){bps1=spi(0xFF);} //bytes per sector 381 else if(i==12){bps2=spi(0xFF);} 382 383 else if(i==13){SectorsPerCluster=spi(0xFF);} 384 else if(i==14){rs1=spi(0xFF);} 385 386 else if(i==15){rs2=spi(0xFF);} 387 else if(i==16){Fats=spi(0xFF);} //number 388 of FATs 389 else if(i==36){spf[0]=spi(0xFF);} 390 else if(i==37){spf[1]=spi(0xFF);} 391 392 else if(i==38){spf[2]=spi(0xFF);} 393 else if(i==39){spf[3]=spi(0xFF);} 394 395 else if(i==44){rdc[0]=spi(0xFF);} 396 else if(i==45){rdc[1]=spi(0xFF);} 397 398 else if(i==46){rdc[2]=spi(0xFF);} 399 else if(i==47){rdc[3]=spi(0xFF);} 400 401 else{spi(0xFF);} 402 403 } 404 spi(0xFF); //discard of CRC 405 spi(0xFF); 406 407 digitalWrite(CS, HIGH); 408 spi(0xFF); 409 410 BytesPerSector = bps1 | 411 ( (unsigned int)bps2 << 8 ); 412 ReservedSectors = rs1 | ( (unsigned int)rs2 << 413 8 ); //from partition start to first FAT 414 RootDirCluster = rdc[0] | ( (unsigned 415 long)rdc[1] << 8 ) | ( (unsigned long)rdc[2] << 16 ) | ( (unsigned long)rdc[3] << 416 24 ); 417 SectorsPerFat = spf[0] | ( (unsigned long)spf[1] << 8 ) | ( (unsigned 418 long)spf[2] << 16 ) | ( (unsigned long)spf[3] << 24 ); 419 DataSector = BootSector 420 + (unsigned long)Fats * (unsigned long)SectorsPerFat + (unsigned long)ReservedSectors; 421 // + 1 422 RootDir = (RootDirCluster -2) * (unsigned long)SectorsPerCluster 423 + DataSector; 424} 425 426unsigned char spi(unsigned char data) // send character 427 over spi 428{ 429 SPDR = data; // Start transmission 430 while(!(SPSR & _BV(SPIF))); 431 // Wait for transmission to complete 432 return SPDR; // received byte 433 434} 435 436 //assemble a 32 bits command 437char Command(unsigned char frame1, unsigned 438 long adrs, unsigned char frame2 ) 439{ 440 unsigned char i, res; 441 spi(0xFF); 442 443 spi((frame1 | 0x40) & 0x7F); //first 2 bits are 01 444 spi((adrs & 0xFF000000) 445 >> 24); //first of the 4 bytes address 446 spi((adrs & 0x00FF0000) >> 16); 447 448 spi((adrs & 0x0000FF00) >> 8); 449 spi(adrs & 0x000000FF); 450 spi(frame2 | 451 1); //CRC and last bit 1 452 453 for(i=0;i<10;i++) // wait for received 454 character 455 { 456 res = spi(0xFF); 457 if(res != 0xFF)break; 458 } 459 460 return res; 461} 462 463void InitSD(void) 464{ 465 unsigned char i,r[4]; 466 467 468 digitalWrite(CS, HIGH); 469 for(i=0; i < 10; i++)spi(0xFF); // min 74 470 clocks 471 digitalWrite(CS, LOW); // Enabled for spi mode 472 473 i=100; 474 //try idle state for up to 100 times 475 while(Command(0x00,0,0x95) !=1 && i!=0) 476 477 { 478 digitalWrite(CS, HIGH); 479 spi(0xFF); 480 digitalWrite(CS, LOW); 481 482 i--; 483 } 484 if(i==0) error(); //idle failed 485 486 if (Command(8,0x01AA,0x87)==1){ 487 //check card is 3.3V 488 r[0]=spi(0xFF); r[1]=spi(0xFF); r[2]=spi(0xFF); 489 r[3]=spi(0xFF); //rest of R7 490 if ( r[2] == 0x01 && r[3] == 0xAA ){ //Vdd 491 OK (3.3V) 492 493 //Command(59,0,0xFF); //CRC off 494 Command(55,0,0xFF); 495 496 while(Command(41,0x40000000,0xFF)){Command(55,0,0xFF);} //ACMD41 with HCS 497 bit 498 } 499 }else{error();} 500 501 if (Command(58,0,0xFF)==0){ //read 502 CCS in the OCR - SD or SDHC 503 r[0]=spi(0xFF); r[1]=spi(0xFF); r[2]=spi(0xFF); 504 r[3]=spi(0xFF); //rest of R3 505 sdhc=r[0] & 0x40; 506 //if(r[0] & 0x40)sdLED=1; 507 508 } 509 SPCR &= ~(_BV(SPR1)); // set clock rate fck/8 = 2MHz 510 digitalWrite(CS, 511 HIGH); 512} 513 514
Downloadable files
arduino clock2
arduino clock2
Comments
Only logged in users can leave comments
spudnut1
2 years ago
Sorry. The talking clock is not my project. I think you sent to the wrong email address. Irwin L. Goverman (206)930-2108 mobile Sent from my iPhone
Anonymous user
2 years ago
I have a school project requiring temp and humidity and I want to combine the talking function with these. Any advice?
spudnut1
2 years ago
Great project. It'd be a lot easier to use the Adafruit FX Soundboard to do all the file management, decoding and announcing.... Just a thought!
Anonymous user
2 years ago
This project is awesome.The only thing is when ever switch off, the time goes to default.Every time we are adjusting the current time. Kindly publish necessary correction.Thank you.
Anonymous user
2 years ago
i had assembled all while power ON showing SD ERROR. kindly help me. I had formatted the micro SD on FAT32 .kindly help me. Thank you
spudnut1
2 years ago
Sorry. The talking clock is not my project. I think you sent to the wrong email address. Irwin L. Goverman (206)930-2108 mobile Sent from my iPhone
basssman72
3 years ago
I have a school project requiring temp and humidity and I want to combine the talking function with these. Any advice?
spudnut1
5 years ago
Great project. It'd be a lot easier to use the Adafruit FX Soundboard to do all the file management, decoding and announcing.... Just a thought!
moty
5 Followers
•15 Projects
8
9
Anonymous user
2 years ago
i had assembled all while power ON showing SD ERROR. kindly help me. I had formatted the micro SD on FAT32 .kindly help me. Thank you