Forum: Compiler & IDEs Kapazitiver Sensor mit ATTiny13 - Bascom > C


von Дмитрий Л. (gottdrak99)


Lesenswert?

Hallo zusammen,

ich habe folgende Seite http://www.elektronik-labor.de/AVR/Touch.html 
als Referenz genutzt, um einen kapazitiven Sensor für ATTiny13 
nachzubauen. Da meine Bascom Kenntnisse eher bescheiden sind, habe ich 
versucht die paar Zeilen ins C zu übersetzen. Leider will meine LED mit 
C Code nicht leuchten.
Mit Bascom funktioniert dies einwandfrei (auch mit 9.6 Mhz anstatt mit 
1.2 Mhz)

// Kapazitiver Touch-Sensor
// 1,5 nF zwischen B3 und B4
// Sensorplatte an B4
// LED mit 1 k an B1

#define F_CPU 9600000 // 9.6 MHz

#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>

int main(void)
{
  uint16_t i, d;

  DDRB |= (1 << PB1);

  while (1)
  {
    d = 1;

    for (i = 1; i < 1500; i++)
    {
      DDRB &= ~(1 << PB3); // B3 hochohmig
      PORTB |= (1 << PB4); // B4 high
      DDRB |= (1 << PB4); // B4 niederohmig

      if (!(PINB & (1 << PB3)))
        break;

      DDRB &= ~(1 << PB4); // B4 hochohmig
      PORTB &= ~(1 << PB4); // ohne Pullup
      DDRB |= (1 << PB3); // B3 high

      d++;
    }

    PORTB &= ~(1 << PB3);
    PORTB &= ~(1 << PB4);
    DDRB |= (1 << PB3);
    DDRB |= (1 << PB4);

    if (d < 5)
      PORTB |= (1 << PB1);
    else
      PORTB &= ~(1 << PB1);

    _delay_ms(50);
  }
}

von Karl H. (kbuchegg)


Lesenswert?

So wie ich das gesehen habe, hast du das BASCOM Programm korrekt 
umgesetzt.
Nur eines:
Da ich erwarten würde, dass das C Programm schneller arbeitet als 
BASCOM, müsstest du doch die Abfrage

    if (d < 5)

erhöhen und nicht erniedrigen. Das C Programm würde d in derselben Zeit 
(die Zeit ist ja durch den Kondensator vorgegeben) potentiell höher 
zählen als BASCOM

aus Bascoms   d < 30
würde ich mal d < 40 (50, 60, 70) machen.

von Дмитрий Л. (gottdrak99)


Lesenswert?

Ich habe festgestellt dass die Variable d am Ende der Prüfung immer 2 
ist.

Sprich mit

    if (d == 2)
      PORTB |= (1 << PB1);
    else
      PORTB &= ~(1 << PB1);

leuchtet die LED dauerhaft.

Das bedeutet er steigt bereits beim zweiten Durchlauf aus.
Ein größerer Kondensator bringt auch kein Licht ins Dunkle...

von Peter D. (peda)


Lesenswert?


von Дмитрий Л. (gottdrak99)


Lesenswert?

Danke für die Unterstützung. Es funktioniert soweit sehr zuverlässig.
Sollte jemand ein ATTiny13 als Touch nutzen, stelle ich vorsichtshalber 
mein C Code hier rein.

Wenn die Initialisierung OK ist, leuchtet die LED für 1 Sekunde auf.
1
#define F_CPU 9600000 // 9.6 MHz
2
3
#include <avr/io.h>
4
#include <util/atomic.h>
5
#include <stdint.h>
6
#include <util/delay.h>
7
8
#define SK_A0   (1 << 3)
9
#define SK_B0   (1 << 4)
10
11
#define SK_A012 (SK_A0)
12
#define SK_B012 (SK_B0)
13
14
#define OBSERVATIONAL_ERROR   3
15
16
uint16_t keys[1];
17
18
void read_senskey(void)
19
{
20
  uint16_t i = 2000;
21
  uint8_t a, b, x, y;
22
23
  ATOMIC_BLOCK(ATOMIC_FORCEON)
24
  {
25
    a = DDRB  & ~(SK_A012 | SK_B012);
26
    b = PORTB & ~(SK_A012 | SK_B012);
27
    y = SK_B012;                  // input mask
28
    
29
    do
30
    {
31
      DDRB = a;                   // tristate
32
      PORTB = b | SK_B012;
33
      DDRB = a | SK_B012;         // Bx = strong high
34
      DDRB = a;                   // tristate
35
      PORTB = b;
36
      DDRB = a | SK_A012;         // Ax = strong low
37
38
      if( --i == 0 )              // timeout
39
        break;
40
41
      x = y & PINB;               // not immediately after set DDRB !!!
42
      if(x)
43
        if( x & SK_B0 )
44
          keys[0] = i;
45
46
      y ^= x;                     // clear processed input
47
    } while(y);                   // all inputs done
48
49
    DDRB = a | SK_A012 | SK_B012; // discharge
50
  }
51
}
52
53
int main(void)
54
{
55
  DDRB |= (1 << PB1); // Sensor LED
56
57
  // init default value
58
  uint16_t initvalue;
59
  do
60
  {
61
    initvalue = keys[0];
62
    for (int j = 1; j < 255; j++)
63
      read_senskey();
64
  } while (initvalue != keys[0]);
65
66
  // init ok
67
  PORTB |= (1 << PB1);
68
  _delay_ms(1000);
69
  PORTB &= ~(1 << PB1);
70
71
  while (1)
72
  {
73
    read_senskey();
74
75
    if (initvalue - OBSERVATIONAL_ERROR < keys[0])
76
      PORTB |= (1 << PB1);
77
    
78
    if (initvalue + OBSERVATIONAL_ERROR > keys[0])
79
      PORTB &= ~(1 << PB1);
80
81
    _delay_ms(150);
82
  }
83
}

von Thomas S. (tstag)


Lesenswert?

TOP, vielen Dank! Hab ewig rumgeschustert und nichts zustande gebracht 
bis ich endlich deinen Beitrag gefunden hab! Danke!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.